您的位置:首页 > 其它

快速排序实现以及时间复杂度分析

2017-09-30 22:55 465 查看
原文:http://www.cnblogs.com/fengty90/p/3768827.html

之前只知道快速排序的平均时间复杂度为O(n×log(n)),最糟糕时复杂度为O(n^2),但却不知道具体原因,今天好好证明一下,最后部分摘自《算法导论》。

首先再介绍一遍快排的思想:

通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。


1、最优情况

在最优情况下,Partition每次都划分得很均匀,如果排序n个关键字,其递归树的深度就为 [log2n]+1( [x] 表示不大于 x 的最大整数),即仅需递归 log2n 次,需要时间为T(n)的话,第一次Partiation应该是需要对整个数组扫描一遍,做n次比较。然后,获得的枢轴将数组一分为二,那么各自还需要T(n/2)的时间(注意是最好情况,所以平分两半)。于是不断地划分下去,就有了下面的不等式推断:



n/4 n/8都是等于1,所以式子转化为nT(1)

这说明,在最优的情况下,快速排序算法的时间复杂度为O(nlogn)。


2、最糟糕情况

然后再来看最糟糕情况下的快排,当待排序的序列为正序或逆序排列时,且每次划分只得到一个比上一次划分少一个记录的子序列,注意另一个为空。如果递归树画出来,它就是一棵斜树。此时需要执行n‐1次递归调用,且第i次划分需要经过n‐i次关键字的比较才能找到第i个记录,也就是枢轴的位置,因此比较次数为 ,最终其时间复杂度为O(n^2)。


3、一般情况

最后来看一下一般情况,平均的情况,设枢轴的关键字应该在第k的位置(1≤k≤n),那么:



本来想按这种思路推导出来,结果发现半天推不出结果,最后去翻阅《算法导论》7.4节,发现证明过程还是蛮复杂的,我就偷懒贴一下好了~











下面参考: http://m.blog.csdn.net/yuanba_xs/article/details/61932665
快速排序思想:

1.选择数组左边第一个元素为枢轴pivot,把数组所有元素比pivot大的放在数组右边,比pivot小的放在左边

(复杂度为O(n)欧(n))

2.对pivot左右两边的序列分别进行快速排序。

平均时间复杂度分析:

T(1) = 1;(1个时间单位(比如计算一个数排序需要的时间))

T(n) = 2*T(n/2) + a*n;(a为常数,每次合并时,复杂度为O(n))

= 2*(2*T(n/4)+a*n/2) + a*n

= 4*T(n/4) + 2*a*n

= 4*(2*T(n/8)+a*n/4) + 2*a*n

= 8*T(n/8) + 3*a*n

=......

= 2^k*T(1) + k*a*n  (其中n==2^k,即k=log2(n))

= n + a*n*log2(n);

所以时间复杂度为O(nlogn) 欧(nlogn)

注意:对左右分别快排时,可能出现一遍元素个数为0,这是最坏情况,此时时间复杂度为O(n^2)

#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 10005
using namespace std;

int a
;

void Qsort(int a[], int s, int e)
{
if (s >= e)//待排元素个数<1
return;

int pivot = a[s], i = s, j = e;
while (i < j)
{
while (i < j && a[j] >= pivot)
j--;
swap(a[i], a[j]);
while (i < j && a[i] <= pivot)
i++;
swap(a[i], a[j]);
}
Qsort(a, s, i - 1);
Qsort(a, i + 1, e);
}

int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
Qsort(a, 0, n - 1);//待排数组,以及序列下标始末位置。
for (int i = 0; i < n; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐