快速排序的原理与优化

快速排序基本思想和时间复杂度分析转载:点击打开链接

快速排序的基本思想是:每次从无序的序列中找出一个数作为中间点(可以把第一个数作为中间点),然后把小于中间点的数放在中间点的左边,把大于中间点的数放在中间点的右边;对以上过程重复log2n次得到有序的序列。

    快速排序的时间复杂性分析:排序的大体如下图所示,假设有1到8代表要排序的数,快速排序会递归log28=3次,每次对n个数进行一次处理,所以他的时间复杂度为n*log(n)。所以排序问题的时间复杂度可以认为是对排序数据的总的操作次数。



下面对于一些优化作详解:转载链接:百度知道关于快排

1.
快速排序-时空复杂度:
快速排序每次将待排序数组分为两个部分,在理想状况下,每一次都将待排序数组划分成等长两个部分,则需要logn次划分。
而在最坏情况下,即数组已经有序或大致有序的情况下,每次划分只能减少一个元素,(这句话的意思是,基准没有选好,想一下顺序的数,每次yoga第一个做基准,用快排的情形,时间复杂度n(n-1)/2,即O(n^2))快速排序将不幸退化为冒泡排序,所以快速排序时间复杂度下界为O(nlogn),最坏情况为O(n^2)。在实际应用中,快速排序的平均时间复杂度为O(nlogn)。
快速排序在对序列的操作过程中只需花费常数级的空间。空间复杂度S(1)。
但需要注意递归栈上需要花费最少logn最多n的空间。

2.快速排序-随机化算法:(递归是非常耗系统堆栈的)
快速排序的实现需要消耗递归栈的空间,而大多数情况下都会通过使用系统递归栈来完成递归求解。在元素数量较大时,对系统栈的频繁存取会影响到排序的效率。(主要原因是划分成较小的块时,消耗大)
一种常见的办法是设置一个阈值,在每次递归求解中,如果元素总数不足这个阈值,则放弃快速排序,调用一个简单的排序过程完成该子序列的排序。这样的方法减少了对系统递归栈的频繁存取,节省了时间的消费。
一般的经验表明,阈值取一个较小的值,排序算法采用选择、插入等紧凑、简洁的排序。一个可以参考的具体方案:阈值T=10,排序算法用选择排序。
阈值不要太大,否则省下的存取系统栈的时间,将会被简单排序算法较多的时间花费所抵消。
另一个可以参考的方法,是自行建栈模拟递归过程。但实际经验表明,收效明显不如设置阈值。

3.快速排序的最坏情况基于每次划分对主元的选择。基本的快速排序选取第一个元素作为主元。这样在数组已经有序的情况下,每次划分将得到最坏的结果。一种比较常见的优化方法是随机化算法,即随机选取一个元素作为主元。这种情况下虽然最坏情况仍然是O(n^2),但最坏情况不再依赖于输入数据,而是由于随机函数取值不佳。实际上,随机化快速排序得到理论最坏情况的可能性仅为1/(2^n)。所以随机化快速排序可以对于绝大多数输入数据达到O(nlogn)的期望时间复杂度。一位前辈做出了一个精辟的总结:“随机化快速排序可以满足一个人一辈子的人品需求。”
  
4.随机化快速排序的唯一缺点在于,一旦输入数据中有很多的相同数据,随机化的效果将直接减弱。对于极限情况,即对于n个相同的数排序,随机化快速排序的时间复杂度将毫无疑问的降低到O(n^2)。解决方法是用一种方法进行扫描,使没有交换的情况下主元保留在原位置。
5.其他一些改变枢纽的方法:(转载来自点击打开链接

1、选取随机数作为枢轴。 但是随机数的生成本身是一种代价,根本减少不了算法其余部分的平均运行时间。 2、使用左端,右端和中心的中值做为枢轴元。 经验得知,选取左端,右端,中心元素的中值会减少了快排大约 14%的比较。 3、每次选取数据集中的中位数做枢轴。 选取中位数的可以在 O(n)时间内完成。(证明见《算法导论(第二版) 》) P111 第九章中位数 和顺序统计学:在平均情况下,任何顺序统计量(特别是中位数)都可以在线性时间内得到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值