您的位置:首页 > 其它

排序算法之快速排序

2015-08-19 15:49 260 查看

快速排序的思想:

  分治法,将大问题分为若干个小的问题,解决小问题然后合成大问题的解

典型的快速排序的一般过程:

  1、在数组中找到一个数,一般选作数组最后一个数作为中轴数X

  2、以中轴数X作为中心,使用一次划分partition,使得中轴数左边的数都比X小,右边的数都比X大,换句话说经历过一次划分后,中轴数X处在它本来应该在的位置上

  3、递归调用partition,最后使得整个数组有序

一次划分partition过程:

int partition(int data[],int start,int end){
int i=start-1;
int j=start;
int x=data[end];
for(;j<end;j++){
if(data[j]<x){
++i;
exchange(data+i,data+j);
}
}
exchange(data+i+1,data+end);
return i+1;      //i标识的是数组中值小于X的最大下标,i+1即指一次划分后X所在的下标位置
}


递归调用的过程:

void quicksort(int data[],int start,int end){
if(start<end){
int index=partition(data,start,end);
quicksort(data,start,index-1);
quicksort(data,index+1,end);
}
}


注:函数的边界检查条件可以交付给上层调用函数来完成

快速排序的时间复杂度分析:

  上述为了简便说明,总是选取待排序数组的最后一个元素作为中轴数,假设一种极端的情况,待排数组已经有序或者元素值全部相同,进行一次partition划分后,中轴数左右两边的元素个数分别是N-1,0,即每经过一次划分,就仅仅将一个数组元素放置在它应该在的位置上,剩余的N-1个数还需要继续排序,每次划分的时间复杂度为遍历一次待排数组所消耗的时间O(n)

  设整个排序的时间复杂度为T(n),则最坏的情况下,T(n)=T(n-1)+T(0)+O(n),可以递推得T(n)=O(n^2)

  算法的最佳时间复杂度,在最理想的情况下,每次划分总是将待排数组均衡划分,即一次划分完成后,中轴数左右两边的元素个数都是(N-1)/2,则其总的时间复杂度

  T(n)<=2*T(n/2)+O(n),T(n)=O(nlgn)

  算法的平均时间复杂度,T(n)=O(nlgn),(任何一种按常数比例进行的划分都会产生深度为O(lgn)的递归树,每一层的时间复杂度为进行一次划分的时间O(n),所以总的时间复杂度是O(nlgn)----算法导论),可以理解为,如果某一层的划分效果比较差,则该层下面的划分可能会比较好,好差划分随机的分布在递归树的各层,总的划分渐进于每层都是情况好的划分。

快速排序的稳定性:

  由快排的三个过程可以知道,快排不是一种稳定的排序,例如[2,5,6,4(1),7,3,8,4(2)],经历一次划分后,数组变为[2,3,4(2),4(1),7,5,8,6],括号标识第1和第2个4.

快速排序的改进:

  快速排序对于输入数组的随机性有要求,如果待排序的数组元素具有较大的随机性,则排序效果接近于基于比较的排序方法的下限O(nlgn),如果输入的数组基本有序,则不适用于快速排序。

  因此,对于待排序数组,可以给出快排的随机化版本,每次在划分之前,在数组中随机选择一个数T和数组中最后一个数X交换位置,交换过后调用上述partition函数,从而将随机选择的元素T作为中轴数,从而优化排序的性能。

参考资料:《算法导论》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: