您的位置:首页 > 其它

快速排序

2016-04-07 23:58 302 查看
(一)概念及实现

思想:分治策略。

快速排序的原理:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序。

“保证列表的前半部分都小于后半部分”就使得前半部分的任何一个数从此以后都不再跟后半部分的数进行比较了,大大减少了数字间的比较次数。

具体如下(实现为升序):

设数组为a[0…n]。

1. 数组中找一个元素做为基准(base ),通常选数组的第一个数。

2. 对数组进行分区操作。使基准元素左边的值都小于base ,基准元素右边的值都大于等于base 。

3. 将base 值调整到分区后的正确位置。

4. 将基准两边的分区序列,分别进行步骤1~3。(递归)

5. 重复步骤1~4,直到排序完成。

实现代码:

int Division(int a[],int left,int right){
int base = a[left];
while(left<right){
while((left<right) && (a[right]>base))
right--;
a[left] = a[right];
while((left<right) && (a[left]<base))
left++;
a[right] = a[left];
}
a[left] = base;
return left;
}
void QSort(int a[],int left,int right){
int i,tmp;
if((left<0) || (right<0) || (left>right) || (a==NULL))
return;
if(left<right){
i = Division(a,left,right);
QSort(a,i-1,left);
QSort(a,i+1,right);
}


(二)算法复杂度

1. 时间复杂度:O(nlog2n)

快速排序耗时的操作有:比较 + 交换(每次交换两次赋值)。时间复杂度如下:

1) 最好情况:选择的基准值刚好是中间值,分区后两分区包含元素个数接近相等。因为,总共经过x次分区,根据2^x<=n得出x=log2n,每次分区需用n-1个元素与基准比较。所以O(nlog2n)

2) 最坏情况:每次分区后,只有一个分区包含除基准元素之外的元素。这样就和冒泡排序一样慢,需n(n-1)/2次比较。即O(n^2)

3) 渐进时间复杂度(平均时间复杂度):O(nlog2n)

2. 空间复杂度:O(1)

从实现原理可知,快速排序是在原输入数组上进行比较分区的(称“就地排序”),所需开辟的辅助空间跟输入数组规模无关,所以空间复杂度为:O(1)

(三)稳定性

快速是不稳定的,会改变相同元素的相对顺序。

(四)优化改进

当每次分区后,两个分区的元素个数相近时,效率最高。所以找一个比较有代表性的基准值就是关键。通常会采取如下方式:

1. 选取分区的第一个元素做为基准值。这种方式在分区基本有序情况下会分区不均。

2. 随机快排:每次分区的基准值是该分区的随机元素,这样就避免了有序导致的分布不均的问题

3. 平衡快排:取开头、结尾、中间3个数据,通过比较选出其中的中值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: