快速排序

快速排序

  • 优点:
    • 原地排序(只需要很小的辅助栈)
    • 时间复杂度:NLgN
  • 缺点:
    • 非常脆弱。有无数例子证明许多错误能致使它在实际运用中只有平方级别的性能

QuickSort是一种分治的算法,将一个数组分为两个小数组,将两部分独立排序。

与MergeSort比较

  • MergeSort将数组分为两个子数组分别排序,然后将排好序的子数组Merge
    • 递归调用位于处理整个数组之前
    • 将数组分为两半
  • QuickSort是当两个子数组都有序的时候,父数组自然有序了
    • 递归调用位于处理整个数组之后(即partition之后)
    • partition位置取决于数组的内容

关键在于partition

使得数组满足3个条件:

  • 对于某个j,a[j]已经排定
  • a[lo]到a[j-1]中的所有元素都不大于a[j]
  • a[j+1]到a[hi]中的所有元素都不小于a[j]

切分的实现

一般选择a[lo]作为切分元素

我们先从数组左端开始扫描,找到第一个比切分元素大的元素,然后从数组右端开始找到第一个比切分元素小的元素。显然这两个元素是没有排定的,因此我们交换它们的位置。如此继续,我们可以保证左指针i左侧的元素都不大于切分元素,右指针j的右侧元素都不小于切分元素。当两个指针相遇的时候,将切分元素与左子数组最右侧的元素交换位置即可。

算法正确性

由于切分过程总是能排定一个元素,由归纳法可知一定能正确递归将整个数组排序

性能特点

QuickSort的内循环会用一个递增的index将数组的元素和一个定值比较(切分元素),shell sort 和 merge sort慢的原因在于它们在内层循环中移动元素

Quick sort另一速度优势在于比较次数少.

但是排序效率还是取决于切分数组的效果,切分实际上有可能发生于一个数组的任何位置。理想情况是将数组对半分。在这种情况下,quick sort所需的比较次数满足Cn = 2Cn/2 + N
.2Cn/2表示两个子数组的比较成本,N表示需要让左右指针于数组中间处相遇的比较次数.

如果第一次从最小的元素开始切分,第二次从第二小的元素切分,那么大数组每次都要被切分,效率极低,因此在排序之前将数组随机排序的主要原因就是要避免这种情况。

相关数学命题

命题K(按照算法书上的顺序)

将长度为N的无重复数组排序,快速排序平均需要~2NLnN次比较以及1/6NLnN的交换.具体证明见书

命题L

快速排序最多需要N^2/2次比较,但随机打乱数组能够预防这种情况。即:

若每次排序后总有其中一个数组是空的,则比较次数是∑n = N(N+1)/2 ~ N^2/2.

提升性能的几个方法

1.切换到插入排序

基于以下两点:

  • 对于小数组,快速排序比插入排序要慢
  • 因为递归,快速排序的sort()在小数组中也会调用自己
    方法: if (hi <= lo) return; => if (hi <= lo + 5) { Insertion.sort(a, lo, hi); return;}

2.三取样切分

使用子数组的一小部分元素的中位数来切分数组,取样大小为3并用大小剧中的元素切分效果最好.

3.熵最优的排序

简单的想法是将数组切分为三部分,分别对应于小于,等于,大于切分元素的数组元素.

Dijkstra解法:
维护一个lt指针,使得a[lo..lt-1]中的元素都小于v,一个gt指针使得a[gt+1..hi]中的元素都大于v,一个指针i使得a[lt..i-1]中的元素都等于v,a[i..gt]中的元素待定.

  • a[i]小于v,交换a[lt]和a[i], lt和i ++
  • a[i]大于v,交换a[i]和a[gt], --gt
  • a[i]等于v, ++i

对于只有若干不同主键的随机数组,MergeSort的时间复杂度是NLgN,而quick3way则是线性的。3way的最坏情况正是所有主键不同,当存在重复主键时,性能会比merge sort好很多。三向切分是信息量最优的(熵值最低),对于任意分布的输入,最优的基于比较的算法平均所需的比较次数和3way切分的quicksort平均所需比较次数处于常数因子范围内。

3way运行时间与输入的信息量的N倍成正比。实际运用中这个性质很重要,因为对于包含大量重复元素的数组,它将排序时间从线性对数降到了线性级别。这和元素的顺序没有关系,因为会事先打乱以避免前文所提到的最坏情况。

有人提出了不基于比较的排序算法,但仍然是quicksort的表现最优良见后文

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

推荐阅读更多精彩内容

  • 数据结构与算法——快速排序 快速排序,顾名思义,它速度很快,针对一般应用中各种不同的输入都要比其他排序算法快很多,...
    sunhaiyu阅读 3,184评论 0 3
  • 算法简介 是一种分治的排序算法,特点就是快,而且效率高。 基本思路 通过一趟排序将待排元素分隔成独立的两部分,其中...
    TinyDolphin阅读 3,354评论 0 3
  • quicksort可以说是应用最广泛的排序算法之一,它的基本思想是分治法,选择一个pivot(中轴点),将小于pi...
    黎景阳阅读 414评论 0 1
  • 1.基本特点 ①原地排序(之U型要很小的辅助栈)②将长度为N的数组排序所需要的时间和NlgN成正比(平均排序)快速...
    不会code的程序猿阅读 544评论 0 0
  • 度重なる高熱で疲弊し、最早歩くことすら侭ならぬ。食事も受け付けず、繋がれた点滴から水分や栄養を補給しなくてはならな...
    波沙诺瓦阅读 311评论 0 0