JS快速排序

前言

这两天看到阮一峰前辈的快排引起的一系列事件...(居然DDOS都出来了),前端界又被顺路diss了一番,想起来了以前在有道云中记得笔记,顺便在这里再记录下。

快速排序

快速排序采用了一种分治的策略,通常称其为分治法,其基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。

快速排序的具体过程如下:

  1. 在待排序的n个记录中任取一个记录,以该记录的排序码为准,将所有记录分成两组,第1组各记录的排序码都小于等于该排序码,第2组各记录的排序码都大于该排序码,并把该记录排在这两组中间。
  2. 采用同样的方法,对左边的组和右边的组进行排序,直到所有记录都排到相应的位置为止。

算法复杂度
最好的情况下:因为每次都将序列分为两个部分(一般二分都复杂度都和logN相关),故为 O(NlogN)
最坏的情况下:基本有序时,退化为冒泡排序,几乎要比较N
N次,故为O(N*N)
稳定性
由于每次都需要和中轴元素交换,因此原来的顺序就可能被打乱。如序列为 5 3 3 4 3 8 9 10 11会将3的顺序打乱。所以说,快速排序是不稳定的!

一种比较容易理解的方式

这个例子是原地快排,阮老师文章中为非原地快排。

假设我们现在对[3,2,6,7,0,9,1,4,5,8]这个10个数进行排序。

  1. 找一个数作为基准数(就是一个用来参照的数)。

为了方便,就让第一个数3作为基准数。接下来,需要将这个序列中所有比基准数大的数放在3的右边,比基准数小的数放在3的左边。

方法其实很简单:分别从数组两端开始“探测”。先从右往左找一个小于3的数,再从左往右找一个大于3的数,然后交换他们。
这里可以用两个变量i和j,分别指向序列最左边和最右边。刚开始的时候让i指向序列的最左边(即i=0),指向数字3。j指向序列的最右边(即=9),指向数字8。


首先j开始移动j--,直到找到一个小于3的数停下来。因为此处设置的基准数是最左边的数,所以需要让j先出动,这一点非常重要。接下来i++,直到找到一个数大于3的数停下来。最后j指向1,i指向6。

第一次探测

现在交换i j所指的元素的值。交换之后的序列如下:


交换

到此,第一次交换结束。接下来开始j继续向左挪动。移动到0时,比基准数3要小,满足要求,停止移动。i继续向右挪动的,到7之后停了下来。此时再次进行交换,交换之后的序列如下:


第二次交换

第二次交换结束,继续j先开始移动,但是此时i 和 j重合,i和j都到了0面前。说明此轮“探测”结束。我们将基准数3和0进行交换。交换之后的序列如下:

第一轮结束

到此第一轮“探测”真正结束。此时以基准数3为分界点,3左边的数都小于等于3,3右边的数都大于等于3。回顾一下刚才的过程,j的使命就是要找小于基准数的数,i的使命就是要找大于基准数的数,直到i和j重合。

现在基准数3已经归位,它正好处在序列的第3位(从0计数)。此时我们已经将原来的序列,以3为分界点拆分成了两个序列,左边的序列是0 2 1,右边的序列是7 9 6 4 5 8。接下来以同样的方法处理这两个序列即可。

function quickSort(list, low, high) {
    if (low > high)
        return;
    var l = low, h = high;
    var mark = list[low];
    while (l !== h) {
        while (list[h] >= mark && l < h)
            h--;
        while (list[l] <= mark && l < h)
            l++;
        if (l < h) {
            var temp = list[h];
            list[h] = list[l];
            list[l] = temp;
        }
    }
    list[low] = list[l];
    list[l] = mark;
    quickSort(list, low, l - 1);
    quickSort(list, l + 1, high);
}

必须从右侧开始的原因是
例如上例子右侧的序列7 9 6 4 5 8
当我们先从左边开始时,第一次交换完的序列是
7 5 6 4 9 8
此时i指向5 j指向9
继续,i先移动,找到第一个大于7的元素9,i即与j重合,此时按理论来说,本轮探测已结束,所以要交换基准数和ij重合的数,序列即变成了
9 5 6 4 7 8
我们原本 交换后数字7左边应该是全部小于7,右边全部大于7.但现在不行了。
于是,我们必须从右边开始,也就是从基数的对面开始。

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