快速排序同归并排序一样,也采用的是分治策略。快速排序最终要的步骤是划分子数组,假设有个数组A[p..r]被划分成两个子数组(可能为空)A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每个元素都小于等于A[q],且A[q]小于等于A[q+1..r]中的每个元素。划分过程伪代码如下:
PARTITION(A, p, r)
x <-- A[r]
i <-- p-1
for j <-- p to r-1
do if A[j] <= x
then i <-- i+1
exchange A[i] <--> A[j]
exchange A[i+1] <--> A[r]
return i+1
此过程的c程序如下:
int partition(int A[], int p, int r)
{
int i, j;
int x;
x = A[r];
i = p-1;
for (j = p; j < r; j++) {
if (A[j] <= x) {
swap(&A[++i], &A[j]);
}
}
swap(&A[i+1], &A[r]);
return i+1;
}
快速排序伪代码如下:
QUICKSORT(A, p, r)
if p < r
then q <-- PARTITION(A, p, r)
QUICKSORT(A, p, q-1)
QUICKSORT(A, q+1, r)
c程序如下:
void quick_sort(int A[], int p, int r)
{
int q;
if (p < r) {
q = partition(A, p, r);
quick_sort(A, p, q-1);
quick_sort(A, q+1, r);
}
}
例如数组{2, 8, 7, 1, 3, 5, 6, 4},排序过程是这样的:
(1) 2 8 7 1 3 5 6 4(主元)
(2) 2 1 3 4 7 5 6 8
x为主元r,i为-1,j初值为0,因为A[0]为2小于x,所以i加1之后为0,然后交换A[0]和A[0]的值,因为相同所以原数组不变。i不变,j++到3,此时A[3]为1小于x,i加1之后为1,交换A[1]和A[3]的值,原数组变为2 1 7 8 3 5 6 4。j++到4,再交换A[2]和A[4]的值,交换后数组为2 1 3 8 7 5 6 4。j++,后面没有比x再小的数,所以for循环结束,再交换A[3]和A[7]的值,数组变为2 1 3 4 7 5 6 8,并返回3。
(3) 1 2 3 4 7 5 6 8
这样数组A被划分成了两个数组{2, 1, 3}和{7, 5, 6, 8},然后再对这两个数组进行快速排序。{2, 1, 3}数组主元为3,首先是2和2互换不变,1和1互换不变,最后3与3互换不变,这样{2, 1, 3}数组再分成两个数组{2, 1}和{3}。再对{2, 1}数组进行排序,变为{1, 2}。
{4} 1 2 3 4 5 6 7 8
再对数组{7, 5, 6, 8}进行排序,再分成两个数组{7, 5, 6}和{8},{7, 5, 6}数组排序之后变为{5, 6, 7}。
最后,完整程序如下:
#include <stdio.h>
void dump(int a[], int len)
{
int i;
for (i = 0; i < len; i++) {
printf("%3d", a[i]);
}
printf("\n");
}
void swap(int *a, int *b)
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
int partition(int A[], int p, int r)
{
int i, j;
int x;
x = A[r];
i = p-1;
for (j = p; j < r; j++) {
if (A[j] <= x) {
swap(&A[++i], &A[j]);
}
}
swap(&A[i+1], &A[r]);
return i+1;
}
void quick_sort(int A[], int p, int r)
{
int q;
if (p < r) {
q = partition(A, p, r);
quick_sort(A, p, q-1);
quick_sort(A, q+1, r);
}
}
int main(void)
{
int a[] = {2, 8, 7, 1, 3, 5, 6, 4};
int len = sizeof(a) / sizeof(a[0]);
dump(a, len);
quick_sort(a, 0, len-1);
dump(a, len);
return 0;
}

浙公网安备 33010602011771号