快速排序(Quick Sort)详解

[003]:http://latex.codecogs.com/svg.latex?$\Theta(\textit%20n\cdot%20log_2(n))$
[004]:http://latex.codecogs.com/svg.latex?$H(X)%20=%20-\sum_{i}{}P(X_i)%20\cdot%20log_2(P(X_i))$
[005]:http://latex.codecogs.com/svg.latex?i%20\in%20[1,n!],%20\forall%20i\in[1,n!]%20%20%20%20P(X_i)%20=\frac{1}{n!}
[006]:http://latex.codecogs.com/svg.latex?H(X)%20=%20-n!\cdot%20\frac{1}{n!}log_2{\frac{1}{n!}}=log_2{(n!)}
[007]:http://latex.codecogs.com/svg.latex?log_2{(n!)}=\Theta(n\cdot%20log_2(n))
[008]:http://latex.codecogs.com/svg.latex?\Theta(n\cdot%20log_2(n))
[009]:http://latex.codecogs.com/svg.latex?-p\cdot%20log_2{p}-(1-p)\cdot%20log_2{(1-p)}
[010]:http://latex.codecogs.com/svg.latex?\frac{\Theta(n\cdot%20log_2(n))}{1}=\Theta(n\cdot%20log_2(n))
[011]:http://latex.codecogs.com/svg.latex?\Theta(n^2)%20%20and%20%20\Theta(n)
[012]:http://latex.codecogs.com/svg.latex?\Omega(n)%20%20and%20%20O(n^2)%20%20and%20%20\Theta(n)
[013]:http://latex.codecogs.com/svg.latex?\Theta(n%20\cdot%20log_2(n))%20%20and%20%20\Theta(n%20\cdot%20log_2(n))
[014]:http://latex.codecogs.com/svg.latex?\Omega(n%20\cdot%20log_2(n))%20%20and%20%20O(n^2)%20%20and%20%20\Theta(n)
[015]:http://latex.codecogs.com/svg.latex?\Theta(n%20\cdot%20log_2(n))
[016]:http://latex.codecogs.com/svg.latex?E(n)=\frac{1}{n}(E(0)+E(n-1))+\frac{1}{n}(E(1)+E(n-2))+...+\frac{1}{n}(E(n-1)+E(0))+n+1=\frac{2}{n}\sum_{i=0}^{n-1}E(i)+n+1%20\Rightarrow
[017]:http://latex.codecogs.com/svg.latex?n%20\cdot%20E(n)=2\cdot%20\sum_{i=0}^{n-1}E(i)+(n+1)\cdot%20n
[018]:http://latex.codecogs.com/svg.latex?(n-1)%20\cdot%20E(n-1)=2\cdot%20\sum_{i=0}^{n-2}E(i)+n\cdot%20(n-1)
[019]:http://latex.codecogs.com/svg.latex?n%20\cdot%20E(n)-(n-1)%20\cdot%20E(n-1)=2\cdot%20E(n-1)+2%20\cdot%20n
[020]:http://latex.codecogs.com/svg.latex?n%20\cdot%20E(n)=(n+1)%20\cdot%20E(n-1)+2%20\cdot%20n
[021]:http://latex.codecogs.com/svg.latex?a_n%20\cdot%20E(n)=b_n%20\cdot%20E(n-1)+c_n
[022]:http://latex.codecogs.com/svg.latex?a_n=n,b_n=n+1,c_n=2\cdot%20n
[023]:http://latex.codecogs.com/svg.latex?s_n%20\cdot%20a_n\cdot%20E(n)=s_n%20\cdot%20b_n\cdot%20E(n-1)+s_n%20\cdot%20c_n
[024]:http://latex.codecogs.com/svg.latex?S_n=s_n\cdot%20a_n%20%20and%20%20S_{n-1}=s_n\cdot%20b_n
[025]:http://latex.codecogs.com/svg.latex?S_n\cdot%20E(n)=S_{n-1}\cdot%20E(n-1)+s_n\cdot%20c_n
[026]:http://latex.codecogs.com/svg.latex?S_n\cdot%20E(n)=S_0\cdot%20E(0)+\sum_{i=0}^{n}s_i\cdot%20c_i
[027]:http://latex.codecogs.com/svg.latex?S_n=s_n\cdot%20a_n%20,S_{n-1}=s_n\cdot%20b_n\Rightarrow%20S_{n-1}=s_n\cdot%20b_n=s_{n-1}\cdot%20a_{n-1}\Rightarrow
[028]:http://latex.codecogs.com/svg.latex?s_n=\frac{s_{n-1}\cdot%20a_{n-1}}{b_n}
[029]:http://latex.codecogs.com/svg.latex?s_n=\frac{a_{n-1}\cdot%20a_{n-2}\cdot%20...\cdot%20a_{1}}{b_n\cdot%20b_{n-1}\cdot%20...\cdot%20b_{2}}
[030]:http://latex.codecogs.com/svg.latex?s_n=\frac{2}{(n+1)\cdot%20n}
[031]:http://latex.codecogs.com/svg.latex?\frac{2}{n+1}\cdot%20E(n)=S_0\cdot%20E(0)+\sum_{i=1}^{n}\frac{4}{i}
[031]:http://latex.codecogs.com/svg.latex?\frac{2}{n+1}\cdot%20E(n)=S_0\cdot%20E(0)+\sum_{i=1}^{n}\frac{4}{i}
[032]:http://latex.codecogs.com/svg.latex?E(n)=2\cdot%20(n+1)\cdot\sum_{i=1}^{n}\frac{1}{i}
[033]:http://latex.codecogs.com/svg.latex?\sum_{i=1}^{n}\frac{1}{i}=log_2(n)+O(1)
[034]:http://latex.codecogs.com/svg.latex?E(n)=\Theta(n\cdot%20log_2(n))
算法研究是计算机科学中重要的一个分支。众多基础算法中,比较排序算法是基础中的基础。本文主要介绍一种经典的比较排序算法----快速排序算法(由Tony Hoare于1961年发表)的基本思路,优点以及时间和空间复杂度分析。

比较排序算法

概念

简单而言,比较排序算法是对两个元素进行比较来决定两个元素的在输出序列中相对位置(谁在前面谁在后面)的排序算法。从数学意义说,比较排序算法要求序列中的元素满足如下两条性质


  • 比较排序算法类似用天平来比较两个物体之间谁的质量大小来排序


    800px-Balance_à_tabac_1850.JPG

图片来自:由Photographie personnelle User:Poussin jean - objet personnel User:Poussin jean,CC BY-SA 3.0,https://commons.wikimedia.org/w/index.php?curid=1681347

时间复杂度下界

首先抛出结论,比较排序算法的下界是![][003] n为序列长度。证明方法有很多,算法导论中用的是决策树模型证明(The decision-tree model)。我在这里想展示另外一种证明方法:信息熵(因为我是通信狗出身,虽然现在已经拜在图灵的门下,但香农仍是我的祖师爷啊)。
熵值的数学表达为![][004]如果序列长度为n,那么对序列排序后则可能有 n! 种结果。如果输入序列是完全随机序列,则每种结果的概率是相等的。具体到比较排序算法和之前的熵值公式![][005]带回熵值公式![][006]算法导论中3.19证明了![][007]也就是说,针对排序而言,一个长度为n的序列,其蕴含的信息量为![][008]接下来我们分析一下一次比较操作所消除的信息量。对于任意的a和b,假设 p 为 a < b 的概率,那么一次比较操作所能消除的信息量C为![][009]对于随机序列,p = 0.5,C=1,这也是C能取到的最大值。所以想用比较操作来完成序列排序,至少要![][010]次比较操作。

常见的比较排序算法

  • 冒泡排序(Bubble Sort)时间复杂度和空间复杂度为![][011]
  • 插入排序(Insertion Sort) 时间复杂度下界,上界以及空间复杂度为![][012]
  • 归并排序(Merge Sort)时间复杂度和空间复杂度为![][013]可见虽然归并排序的时间复杂度符合理论最小值,但它的空间复杂度也很高。更蛋疼的是归并排序的时间复杂度分析是建立在RAM模型(Random Access Memory)上,而实际的计算机内存模型并不是RAM而是有cache的。因为归并排序算法在每次递归迭代过程中都会申请新的内存然后在新申请内存上进行操作。这不匹配于cache内存机制,所以归并排序算法在真实硬件上的表现不很理想。不过随着并行,分布式系统的兴起,这个算法又有了新的生机。它非常适合并行优化,并且已经有了相应分析和研究(如果这篇反响好我第二篇就写这个内容)。

快速排序算法

伪码

快速排序则充分利用了cache机制,算法的伪码是

algorithm quicksort(A, lo, hi) 
    if lo < hi then p := partition(A, lo, hi) 
    quicksort(A, lo, p – 1) 
    quicksort(A, p + 1, hi) 
algorithm partition(A, lo, hi)
    pivot := A[hi] 
    i := lo
    for j := lo to hi – 1 do 
    if A[j] ≤ pivot then 
        swap A[i] with A[j] 
        i := i + 1 
    swap A[i] with A[hi] 
    return i

复杂度分析

显然,快速排序的时间复杂度的下界,上界以及空间复杂度为![][014]看上去并不怎么样。但因为输入序列为随机序列,所以我们还得关注下时间复杂度的期望值。
在算法导论中,快速排序的时间复杂度期望值证明思路如下

  • 猜测其时间复杂度的期望值为![][015]
  • 再用数学归纳法证明

另一种分析方法

但作为强迫症晚期的我总觉得这个方法不够酷炫,因为猜测时间复杂度期望值这一步总有一种碰运气的感觉(当然这是调侃的说法,其实这种思路在数学证明中有时候很有用)。基于此,向大家隆重推出下面这种方法,简直是狂拽酷炫屌炸天(纯个人主观喜好。。。。)。假设E(n)为输入序列长度为n时期望的时间复杂度,则![][016]![][017]那么![][018]两式相减![][019]![][020]我们将这个等式一般化![][021]![][022]接下来我们将一般化后的等式两边变形为![][023]我们假设这个参数选择得非常好,巧妙的满足![][024]所以等式可以变形为![][025]化简![][026]![][027]![][028]迭代则有![][029]我们将![][022]代入后得到![][030]![][031]因为E(0)=0![][032]从算法导论的A.7可知![][033]所以![][034]
上述证明来自于具体数学(concrete mathematics)第二章

总结

时间复杂度的期望值符合理论最小值,并且空间复杂度只有O(n),能够很好的利用cache机制。所以快速排序是很不错的串行比较排序算法,特别是在真实的硬件上,所以gcc中还有qsort这个库函数(stdlib.h)。

第一次用Markdown,输入公式好累啊。。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,585评论 4 365
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,923评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,314评论 0 248
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,346评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,718评论 3 291
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,828评论 1 223
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,020评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,758评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,486评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,722评论 2 251
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,196评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,546评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,211评论 3 240
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,132评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,916评论 0 200
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,904评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,758评论 2 274

推荐阅读更多精彩内容

  • 一. 写在前面 要学习算法,“排序”是一个回避不了的重要话题,在分析完并查集算法和常用数据结构之后,今天我们终于可...
    Leesper阅读 2,465评论 0 40
  • 概述:排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    每天刷两次牙阅读 3,706评论 0 15
  • 最近在读< >时,了解到了很多常用的排序算法,故写一篇读书笔记记录下这些排序算法的思路和实现. 冒泡排序 冒泡排序...
    SylvanasSun阅读 662评论 0 0
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 5,108评论 0 52
  • 四. 走向世界之巅——快速排序 你可能会以为归并排序是最强的算法了,其实不然。回想一下,归并的时间效率虽然高,但空...
    Leesper阅读 1,471评论 9 7