一、快速排序的基本特性
时间复杂度:O(n*lgn)
最坏:O(n^2)
空间复杂度:O(n*lgn)不稳定。
快速排序时基于分治模式处理的,对一个典型子数组A[p...r]排序的分治过程为三个步骤:
1.分解:A[p..r]被划分为两个(可能空)的子数组A[p ..q-1]和A[q+1 ..r],使得A[p ..q-1] <= A[q] <= A[q+1 ..r],下标q在这个划分过程中进行计算。
2.解决:通过递归调用快速排序,对子数组A[p ..q-1]和A[q+1 ..r]排序。
3.合并:因为两个子数组是就地排序的,讲它们的合并不需要操作。
二、快速排序算法的描述
算法导论,第7章P85
PARTITION(A, p, r)
x ← A[r] //以最后一个元素,A[r]为主元
i ← p - 1
for j ← p to r - 1 //注,j从p指向的是r-1,不是r。
do if A[j] ≤ x
then i ← i + 1
exchange A[i] <-> A[j]
exchange 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/c++程序:
首先是,PARTITION过程:
int partition(int data[],int lo,int hi)
{
int key=data[hi]; //以最后一个元素,data[hi]为主元 int i=lo-1;
for(int j=lo;j<hi;j++) ///注,j从p指向的是r-1,不是r。
{
if(data[j]<=key)
{
i=i+1;
swap(&data[i],&data[j]);
}
}
swap(&data[i+1],&data[hi]); //不能改为swap(&data[i+1],&key)
return i+1;
}
补充说明:举个例子,如下为第一趟排序(4步):
a:3 8 7 1 2 5 6 4 //以最后一个元素,data[hi]为主元
b:3 1 7 8 2 5 6 4
c:3 1 2 8 7 5 6 4
d:3 1 2 4 7 5 6 8 //最后,swap(&data[i+1],&data[hi])
而其中swap函数的编写,是足够简单的:
void swap(int *a,int *b)
{
int temp=*a;
*a=*b;
*b=temp;
}
然后是,调用partition,对整个数组进行递归排序:
void QuickSort(int data[], int lo, int hi)
{
if (lo<hi)
{
int k = partition(data, lo, hi);
QuickSort(data, lo, k-1);
QuickSort(data, k+1, hi);
}
}
摘录算法导论上的例子
2 8 7 1 3 5 6 4(主元)
当然,快速排序要很多实现方法,比如:算法导论上的单向扫描版本、双向扫描版(Hoare版本及其变形)、随机化版本、三数取中分割法以及非递归实现。这里不作介绍了,因为July博主总结的非常完善了。见参考。
参考:1.http://blog.csdn.net/v_JULY_v/article/details/6262915
2.http://blog.csdn.net/v_JULY_v/article/details/6116297
3.算法导论第7章,快速排序。