【算法】5 传说中的快排是怎样的

什么是快速排序

快速排序简介

快速排序(英文名:Quicksort,有时候也叫做划分交换排序)是一个高效的排序算法,由Tony Hoare在1959年发明(1961年公布)。当情况良好时,它可以比主要竞争对手的归并排序和堆排序快上大约两三倍。这是一个分治算法,而且它就在原地排序。

所谓原地排序,就是指在原来的数据区域内进行重排,就像插入排序一般。而归并排序就不一样,它需要额外的空间来进行归并排序操作。为了在线性时间与空间内归并,它不能在线性时间内实现就地排序,原地排序对它来说并不足够。而快速排序的优点就在于它是原地的,也就是说,它很节省内存。

引用一张来自维基百科的能够非常清晰表示快速排序的示意图如下:

快速排序的分治思想

由于快速排序采用了分治算法,所以:

一、分解:本质上快速排序把数据划分成几份,所以快速排序通过选取一个关键数据,再根据它的大小,把原数组分成两个子数组:第一个数组里的数都比这个主元数据小或等于,而另一个数组里的数都比这个主元数据要大或等于。

二、解决:用递归来处理两个子数组的排序。 (也就是说,递归地求上面图示中左半部分,以及递归地求上面图示中右半部分。)

三、合并:因为子数组都是原址排序,所以不需要合并操作,通过上面两步后数组已经排好序了。

所以快速排序的主要思想是递归与划分。

如何划分

当然最重要的是它的复杂度是线性的,也就是Θ(n)个划分的子程序。

Partition(A,p,q)   // A[p,..q]
1   x=A[p]   // pivot=A[p] 主元
2   i=p
3   for j=p+1 to q
4       do if A[j]<=x
5          then i=i+1
6             exch A[i]<->A[j]
7   exch A[p]<->A[i]
8   return i // i pivot 

这就是划分的伪代码,基本的结构就是一个for循环语句,中间加上了一个if条件语句,它实现了对子数组A[p...q]的原址排序。

刚开始时i等于p,j等于p+1。在这个循环中查找i下标的数据,如果它比x大,那就将其存放到“>=x”区域并将j加1后进行下一次循环。而如果它比x小,那就要做些动作来维持循环不变量了。将i的下标加1后将下标i对应的数据和下标j所对应的数据互换位置。然后再移动区域的界限并开始下一次循环。

那么这个算法在n个数据下的运行时间大约是O(n),因为它几乎把每个数都比较了一遍,而每个步骤所需的时间都为O(1)。

上面这幅图详细的描述了Partition过程,每一行后也加了注释。

将递归的思想作用于划分上

有了上面这些准备工作,再加上分治的思想实现快速排序的伪代码也是很简单的。

Quicksort(A,p,q)
1   if p<q
2     then r=Partition(A,p,q)
3          Quicksort(A,p,r-1)
4          Quicksort(A,r+1,q) 

为了排序一个数组A的全部元素,初始调用时Quicksort(A,1,A.length)。

快速排序的算法分析

相信通过前面的诸多实践,大家也发现了快速排序的运行时间依赖于Partition过程,也就是依赖于划分是否平衡,而归根结底这还是由于输入的元素决定的。

如果划分是平衡的,那么快速排序算法性能就和归并排序一样。

如果划分是不平衡的,那么快速排序的性能就接近于插入排序。

怎样是最坏的划分

1)输入的元素已经排序或逆向排序
2)每个划分的一边都没有元素

也就是说当划分产生的两个子问题分别包含了n-1个元素和0个元素时,快速排序的最坏情况就发生了。

T(n)=T(0)+T(n−1)+\Theta(n)=Θ(1)+T(n−1)+Θ(n)=Θ(n−1)+Θ(n)=Θ(n2)

这是一个等差级数,就和插入排序一样。它并不比插入排序快,因为当同样是输入元素已经逆向排好序时,插入算法的运行时间为Θ(n)。但快速排序仍旧是一个优秀的算法,这是因为在平均情况下它已经很高效。

我们为最坏情况画一个递归树。

这是一课高度不平衡的递归树,图中左边的那些T(0)的运行时间都为Θ(1),而总共有n个。

所以算法的中运行时间为:

T(n)=Θ(n)+Θ(n2)=Θ(n2)

最坏划分的算法分析

通过上面的图示我们知道了在最坏情况下快速排序的复杂度是Θ(n2),但以图示的方式并不是一种严谨的证明方式,我们应该使用代入法来证明它。

当输入规模为n时,时间T(n)有如下递归式:

T(n)=max0≤r≤n−1(T(r)+T(n−r−1))+Θ(n)

除去主元后,在Partition函数中生成的两个子问题的规模的和为n-1,所以r的规模才是0到n-1。

假设T(n)≤cn2成立,其中c为常数这个大家都知道的。于是上面的递归式为:

T(n)≤max0≤r≤n−1(cr2+c(n−r−1)2)+Θ(n)≤c∗max0≤r≤n−1(r2+(n−r−1)2)+Θ(n)

1)而r2+(n−r−1)2对于r的二阶导数为正,所以在区间0≤r≤n−1的右端点取得最大值。

于是有max0≤r≤n−1(r2+(n−r−1)2)≤(n−1)2=n2−2n+1,所以对于T(n)有:

T(n)≤cn2−c(2n−1)+Θ(n)

最终因为我们可以选择一个足够大的c,来使得c(2n−1)大于Θ(n),所以有T(n)=O(n2)。

2)r2+(n−r−1)2对于r的二阶导数为正,所以在区间0≤r≤n−1的左端点取得最小值。

于是有max0≤r≤n−1(r2+(n−r−1)2)≥(n−1)2=n2−2n+1,所以对于T(n)有:

T(n)≥cn2−c(2n−1)+Θ(n)

同样我们也可以选择一个足够小的c,来使得c(2n−1)小于Θ(n),所以有T(n)=Ω(n2)。

综上这两点得到T(n)=Θ(n2)

怎样是最好的划分

当Partition将数组分为n/2和n/2两个部分时是最高效的。此时有:

T(n)=2T(n/2)+Θ(n)=Θ(nlgn)

怎样是平衡的划分

快速排序的平均运行时间更接近于其最好情况,而非最坏情况。

此处有一个经典的示例,将数组按1:9的比例进行划分会怎样呢?这种划分看似很不平衡,但真的会因此而影响效率么?

其中此时的递归式是:

T(n)=T(110n)+T(910n)+Θ(n)

这里依旧通过递归树来观察一番。

因为每次都减少十分之一,需要减多少次才能达到n呢,也恰好也是以10为底对数的定义。所以左侧的高度为log10n了,相应的右侧的高度为log109n。

所有那些叶子加在一起也只有Θ(n),所以有:

T(n)≤cn∗log109n+Θ(n)

其实T(n)的下界也渐近为nlgn,所以总时间为:

T(n)=Θ(nlgn)

只要划分是常数比例的,算法的运行时间总是O(nlgn)。

随机化快速排序

随机算法的思想

在前面分析快速排序的平均情况性能时,是建立在输入数据的所有排列都是等概率的条件下的,但在实际工程中往往不会总出现这种良好的情况。

【算法】3 由招聘问题看随机算法中我们介绍了随机算法,它使得对于所有的输入都有着较好的期望性能,因此随机化快速排序在有大量数据输入的情况下是一种更好的排序算法。

以下是随机化快速排序的好处:

1)其运行时间不依赖与输入序列的顺序

2)无需对输入序列的分布做任何假设

3)没有 一种特别的输入会引起最差的运行情况

4)最差的情况由随机数产生器决定

随机抽样技术

现在我们来使用一种叫做随机抽样(random sampling)的随机化技术,使用该技术就不再始终采用A[p]作为主元,而是从A[p…q]中随机选择一个元素作为主元。

为了达到这一目的,首先将A[p]与从A[p...q]中随机选出的一个元素交换。

通过对序列p...q的随机抽样,我们可以保证主元元素x=A[p]是等概率地从子数组的q−p+1个元素中选取的。

因为主元元素是随机选择的,我们可以期望在平均情况下对输入数组的划分是比较均衡的。所以对前面的两份伪代码做如下修改:

RANDOMIZED-PARTITION(A,p,q)
1   i=RANDOM(p,q)
2   exchange A[p] with A[i]
3   return PARTITION(A,p,q)
RANDOMIZED-QUICKSORT(A,p,q)
1   if p<q
2       r=RANDOMIZED-PARTITION(A,p,q)
3       RANDOMIZED-QUICKSORT(A,p,r-1)
4       RANDOMIZED-QUICKSORT(A,r+1,q)

有了随机抽样技术后再也不用担心快速排序遇到最坏划分的情况啦,所以说随机化快速排序的期望运行时间是O(nlgn)。




感谢您的访问,希望对您有所帮助。 欢迎大家关注、收藏以及评论。



为使本文得到斧正和提问,转载请注明出处:
http://blog.csdn.net/nomasp


时间: 2024-07-31 05:44:24

【算法】5 传说中的快排是怎样的的相关文章

HDOJ(HDU) 1862 EXCEL排序(类对象的快排)

Problem Description Excel可以对一组纪录按任意指定列排序.现请你编写程序实现类似功能. Input 测试输入包含若干测试用例.每个测试用例的第1行包含两个整数 N (<=100000) 和 C,其中 N 是纪录的条数,C 是指定排序的列号.以下有 N 行,每行包含一条学生纪录.每条学生纪录由学号(6位数字,同组测试中没有重复的学号).姓名(不超过8位且不包含空格的字符串).成绩(闭区间[0, 100]内的整数)组成,每个项目间用1个空格隔开.当读到 N=0 时,全部输入结

poj 2623 快排

一.题目大意 就是求中间的数. 二.AC code 递归快排ac版: #include <iostream> #include <stdio.h> #include <cstring> #include <vector> #include <cmath> #include <algorithm> #include <set> #include <cassert> #include <time.h>

快排QuickSort

1.算法思想: /**      * 一趟快速排序的算法是: 1).设置两个变量I.J,排序开始的时候I:=1,J:=N:      *      * 2)以第一个数组元素作为关键数据,赋值给X,即X:=A[1]:      *      * 3).从J开始向前搜索,即由后开始向前搜索(J:=J-1),找到第一个小于X的值,两者交换:      *      * 4).从I开始向后搜索,即由前开始向后搜索(I:=I+1),找到第一个大于X的值,两者交换:      *      * 5).重复第

c语言题目求帮助--快排

问题描述 c语言题目求帮助--快排 文档下载"> 解决方案 你的cmp函数定义不对,修改为 int cmp(const void * a, const void * b) { return abs(*(int *)b) - abs(*(int *)a); }

关于快排,你知道多少?

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 有朋友公司打算做快排,问我关于快排的事,其实说实话,好久没有接触快排了.可能很多人还不知道什么是快排,简单点说,快排就是快速排名,让指定关键词指定内容快速在搜索引擎获得排名,快排只是这个行业专门造的一个词. 具体点说,你的公司需要做一些长尾关键词的排名,可以交给做快排的人,他们会短时间帮你把你这个关键词排名做起来,在用户搜索这个关键词的时候就

快排的思考

9.9.1 快速排序介绍        终于我们的高手要登场了,如果将来你工作后,你的老板要让你写个排序算法,而你会的算法中竟然没有快速排序,我想你还是不要声张,偷偷去把快速排序算法找来敲进电脑,这样至少你不至于被大伙儿取笑.         事实上,不论是C++ STL.Java SDK或者.NET FrameWork SDK等开发工具包中的源代码里都能找到它的某种实现版本.          快速排序算法最早由图灵奖获得者Tony Hoare设计出来的,他在形式化方法理论,以及ALGOL60

zeromq_传说中最快的消息队列

Zeromq的资源: Zeromq模式: http://blog.codingnow.com/2011/02/zeromq_message_patterns.html zeromq主页: http://www.zeromq.org/ Zeromq Guild: http://zguide.zeromq.org/page:all#Fixing-the-World Zeromq 中文简介: http://blog.csdn.net/program_think/article/details/6687

【技术小火车】万万没想到!原来你是这样的算法君?!

据说算法正在统治世界?吓得我瓜子都掉了......好吧无稽之谈,你们的神之蔑视脸我先收下了,谁让人家单纯无邪天真可爱说啥信啥呢.别闹了,赶紧言归正传(严肃脸).虽然没有那么可怖,但是算法的作用自然不必多说.毕竟无论男男女女老老少少,想在计算机这条道路上走得更远,算法都是不可或缺的. 然而算法千千万,又有哪些算法属于"夜空中的那颗星"呢?本文就带领大家驰骋算法世界,为你展现丰富而又独特的算法之美.简言之嘛,就是咱们一起攻略新副本去!那走着?走啥走,赶紧飞吧!前方一大波福利来袭,千万要Ho

&lt;font color=&quot;red&quot;&gt;[置顶]&lt;/font&gt;

Profile Introduction to Blog 您能看到这篇博客导读是我的荣幸,本博客会持续更新,感谢您的支持,欢迎您的关注与留言.博客有多个专栏,分别是关于 Windows App开发 . UWP(通用Windows平台)开发 . SICP习题解 和 Scheme语言学习 . 算法解析 与 LeetCode等题解 . Android应用开发 ,而最近会添加的文章将主要是算法和Android,不过其它内容也会继续完善. About the Author 独立 Windows App 和