快速排序的C语言实现

时间:2022-06-18 01:17:37

快速排序主要过程如下:
分解:数组A[p..r]被划分为两个(可能为空的)子数列A[p..q-1]和A[q+1..r],使得A[p..q-1]中元素都小于等于A[q],A[q+1..r]中元素都大于A[q]。
解决:通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]进行排序。
合并:因为子数组都是原址排序,所以不需要合并,数组A[p..r]已经有序。
非随机化版本的快速排序实现如下:

int partition(int *source, int head, int tail) {
int x = source[tail];
int i = head - 1, j = head;
for (j = head; j < tail; j++) {
if (source[j] <= x) {
i++;
swap(source + j, source + i);
}
}
swap(source + tail, source + i + 1);
return i + 1;
}

void quick_sort(int *source, int head, int tail) {
if (head >= tail)
return;
int mid = partition(source, head, tail);
quick_sort(source, head, mid - 1);
quick_sort(source, mid + 1, tail);
}

注意,对于一个几乎有序的排列,插入排序的性能往往要优于快速排序。由逆序对内容可知,插入排序的运行时间为 O(n+d) ,其中d为逆序对的数目。又由于一个几乎有序的数列中,逆序对的数目很少,因此插入排序的运行时间接近线性。而上述非随机的快速排序在该种情况下极易产生空的划分,所以在该种情况下,插入排序的性能往往优于快速排序。
随机化版本实现如下:

int randomized_partition(int *source, int head, int tail) {
swap(source + rand() % (tail - head + 1) + head, source + tail);
int x = source[tail];
int i = head - 1, j = head;
for (j = head; j < tail; j++) {
if (source[j] <= x) {
i++;
swap(source + j, source + i);
}
}
swap(source + tail, source + i + 1);
return i + 1;
}

void randomized_quick_sort(int *source, int head, int tail) {
if (head >= tail)
return;
int mid = randomized_partition(source, head, tail);
randomized_quick_sort(source, head, mid - 1);
randomized_quick_sort(source, mid + 1, tail);
}

在划分前,随机选取一个元素于尾部将作为主元的元素交换,再进行划分。