快速排序算法是基于分治策略的一种排序算法。基本思想是,对于输入的子数组a[left : right],按以下三个步骤进行排序:
(1)分解。以a[left]为基准元素将a[left : right]分成三段,a[left : p-1],a[p], a[p+1 : right]。使得a[left : p-1]中的任何一个元素小于a[p],a[p+1 : right]中的任何一个元素大于a[p]。下标p在划分的过程中确定。
(2)递归求解。通过递归调用快速排序算法分别对a[left : p-1]和a[p+1 : right]进行排序。
(3)合并。由于a[left : p-1]和a[p+1 : right]已经排好序了,所以a[left : right]不需任何计算,就已排好序。
代码如下:
#include <stdio.h>
void quick_sort(int[], int, int);
int partition(int[], int, int);
void swap(int*, int*);
int main()
{
int a[20],i=0;
srand(5);
while(i<20) a[i++] = (int)rand(); i=0;
printf("Before sort:\n");
while(i<20) printf("%d\n", a[i++]); i=0;
quick_sort(a, 0, 19);
printf("\nAfter sort:\n");
while(i<20) printf("%d\n", a[i++]);
return 0;
}
void quick_sort(int a[], int left, int right)
{
int p;
if(left < right)
{
p = partition(a, left, right);
quick_sort(a, left, p-1); //对左半段排序
quick_sort(a, p+1, right); //对右半段排序
}
}
int partition(int a[], int left, int right)
{
int i=left, j=right+1, x=a[left];
while(1)
{
while((a[++i] < x) && (i < right)); //从左边开始找一个比x大的元素
while(a[--j] > x); //从右边开始找一个比x小的元素
if(i >= j) break; //如果较大元素的下标比较小元素的大,则说明已完成划分
swap(&a[i], &a[j]);
}
a[left] = a[j];
a[j] = x;
return j; //返回基准元素的下标
}
void swap(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
上述算法中的partation( )函数,用来以一个确定的基准元素a[left](也就是第一个元素)对子数组a[left : right]进行划分。是快速排序算法的关键。
有些细节需要注意。例如,算法中的下标 i 和 j 不会超出a[left : right]的下标界。另外,在快速排序算法中选取a[left]作为基准可以保证算法正常结束。如果选择a[right]作为划分的基准,且a[right]又是a[left : right]中最大的元素,则partition( )返回的值为right,这就会使quick_sort陷入死循环。
对于输入序列a[left : right],partition的计算时间显然为O(r-p-1)。
快速排序的运行时间与划分是否对称有关,器最坏情况发生在划分过程产生的两个区域分别包含n-1个元素和1个元素的时候。这时的时间复杂度为O(n^2)。在最好的情况下,每次划分所去的基准都恰好为中值,即每次划分都产生两个大小为n/2的区域,这时时间复杂度为O(n log n)。
运行结果如下:
Before sort:
590011675
99788765
2131925610
171864072
317159276
171035632
602511920
963050649
1069979073
1919854381
33661026
589806848
2086105860
475191198
894416410
550050020
780437020
583787226
893281828
550277486
After sort:
33661026
99788765
171035632
171864072
317159276
475191198
550050020
550277486
583787226
589806848
590011675
602511920
780437020
893281828
894416410
963050649
1069979073
1919854381
2086105860
2131925610