排序算法系列之——快速排序

作為程序員必備課題之一的算法系列中糊余,排序這個(gè)最為常見(jiàn)的算法實(shí)現(xiàn)也是很有必要掌握的霍殴,所以做一個(gè)系列的總結(jié),便于交流學(xué)習(xí)

廢話少說(shuō)帝簇,進(jìn)入正題

如有誤徘郭,辛苦指正

背景介紹

\color{#ea4335}{快速排序}(Quicksort)是對(duì)\color{#ea4335}{冒泡排序}的一種改進(jìn)靠益。

快速排序由\color{#4285f4}{C. A. R. Hoare}在1960年提出。它的基本思想是:通過(guò)一趟排序?qū)⒁判虻臄?shù)據(jù)分割成獨(dú)立的兩部分残揉,其中一部分的所有數(shù)據(jù)都比另外一部分的所有數(shù)據(jù)都要小胧后,然后再按此方法對(duì)這兩部分?jǐn)?shù)據(jù)分別進(jìn)行快速排序,整個(gè)排序過(guò)程可以\color{#34a853}{遞歸進(jìn)行}抱环,以此達(dá)到整個(gè)數(shù)據(jù)變成\color{#34a853}{有序序列}绩卤。 --- 快速排序算法

核心特點(diǎn)

(1)、在所需要排序的集合中江醇,選擇一個(gè)元素作為"基準(zhǔn)"(pivot)。
(2)何暇、然后以這個(gè)基準(zhǔn)值作為判斷依據(jù)陶夜,小于它則放到他的左邊,反之則放到另一邊裆站。
(3)条辟、最后對(duì)兩遍不停的重復(fù)步驟2,是的最終只剩下一個(gè)元素位置宏胯。

舉個(gè)例子

[ 1, 5, 4, 3, 6, 2, 7 ]

我們隨便定一個(gè)基準(zhǔn)值羽嫡,假設(shè)為3,那么根據(jù)核心特點(diǎn)肩袍,第一次執(zhí)行完畢后得到兩個(gè)數(shù)組

小于3的:[ 1, 2 ]
大于3的:[ 5, 4, 6, 7]

將小于3的的數(shù)組重復(fù)執(zhí)行步驟杭棵,根據(jù)核心特點(diǎn),最后退出的條件是元素為1氛赐,所以小于3的數(shù)組最終為

[ 1, 2 ]

再將大于3的數(shù)組做同樣的操作魂爪,假設(shè)基準(zhǔn)值為6得到

小于6的:[ 5, 4 ]
大于6的:[ 7 ]

......
重復(fù)操作后最終將所有的數(shù)組連接起來(lái)即可
此時(shí)應(yīng)該大概了解了快速排序的算法流程,但是對(duì)細(xì)節(jié)還略有模糊艰管,那么我們?cè)诮Y(jié)合代碼做理解

代碼示例

1滓侍、我們創(chuàng)建一個(gè)排序方法,并接受一個(gè)參數(shù)牲芋,就是我們需要排序的數(shù)組

function quickSort( _array ){
    
}

2撩笆、我們需要設(shè)定一個(gè)基準(zhǔn)值,并創(chuàng)建兩個(gè)數(shù)組用來(lái)存放小于/大于基準(zhǔn)值的數(shù)的集合

function quickSort( _array ){
    //假設(shè)我取了數(shù)組中間的數(shù)作為基準(zhǔn)值缸浦,得到他的下標(biāo), 我們使用~~來(lái)獲取值為floor時(shí)的整數(shù)部分夕冲,也可以使用Math.floor()來(lái)實(shí)現(xiàn)
    var _pivot_index = ~~( _array.length / 2 );
    //基準(zhǔn)值
    var _pivot = _array.splice(_pivot_index, 1)[0];
    //我們需要兩個(gè)數(shù)組來(lái)存放大于小于基準(zhǔn)值的集合
    var _left = [] ,
        _right = [];
}

3、我們先來(lái)進(jìn)行一次循環(huán)餐济,將大于/小于基準(zhǔn)值的數(shù)的集合耘擂,區(qū)分開來(lái)

function quickSort( _array ){
    //假設(shè)我取了數(shù)組中間的數(shù)作為基準(zhǔn)值,得到他的下標(biāo), 我們使用~~來(lái)獲取值為floor時(shí)的整數(shù)部分絮姆,也可以使用Math.floor()來(lái)實(shí)現(xiàn)
    var _pivot_index = ~~( _array.length / 2 );
    //基準(zhǔn)值
    var _pivot = _array.splice(_pivot_index, 1)[0];
    //我們需要兩個(gè)數(shù)組來(lái)存放大于小于基準(zhǔn)值的集合
    var _left = [] ,
        _right = [];
    for( var i = 0; i < _array.length; i++){
        //這里進(jìn)行判斷醉冤,如果大于基準(zhǔn)值則放到右側(cè)數(shù)組秩霍,反之則放到左側(cè)
        _array[i] > _pivot ? _right.push( _array[i] ) : _left.push( _array[i] );
    }
}

4、這樣我們區(qū)分?jǐn)?shù)組就已經(jīng)完成了蚁阳,接下來(lái)我們就是要將左右兩個(gè)數(shù)組铃绒,分別作為參數(shù)傳進(jìn)來(lái),執(zhí)行相同的操作螺捐,那么順理成章的我們就想到了遞歸實(shí)現(xiàn), 所以我門增加一個(gè)return 遞歸操作

function quickSort( _array ){
    // 假設(shè)我取了數(shù)組中間的數(shù)作為基準(zhǔn)值颠悬,得到他的下標(biāo), 我們使用~~來(lái)獲取值為floor時(shí)的整數(shù)部分,也可以使用Math.floor()來(lái)實(shí)現(xiàn)
    var _pivot_index = ~~( _array.length / 2 );
    //基準(zhǔn)值
    var _pivot = _array.splice(_pivot_index, 1)[0];
    // 我們需要兩個(gè)數(shù)組來(lái)存放大于小于基準(zhǔn)值的集合
    var _left = [] ,
        _right = [];
    for( var i = 0; i < _array.length; i++){
        // 這里進(jìn)行判斷定血,如果大于基準(zhǔn)值則放到右側(cè)數(shù)組赔癌,反之則放到左側(cè)
        _array[i] > _pivot ? _right.push( _array[i] ) : _left.push( _array[i] );
    }
    // 因?yàn)槲覀冏罱K要將拆分的數(shù)組連接起來(lái),所以這里可以使用concat方法
    // 遞歸左邊的數(shù)組 連接基準(zhǔn)值 在鏈接遞歸右邊的數(shù)組
    return quickSort( _left ).concat( [ _pivot ], quickSort( _right ) );
}

5澜沟、最后我們知道灾票,遞歸的一個(gè)必要點(diǎn)就是退出條件,否則程序會(huì)進(jìn)入死循環(huán)茫虽,根據(jù)上面的核心特點(diǎn)我們知道刊苍,此時(shí)退出的條件就是當(dāng)數(shù)組的長(zhǎng)度小于等于1時(shí),遞歸退出濒析,那么我們?cè)谧铋_始增加一個(gè)if判斷

function quickSort( _array ){
     // 這里我們?cè)黾右粋€(gè)遞歸退出條件正什,當(dāng)數(shù)組長(zhǎng)度小于等于1時(shí),退出
    if ( _array.length <= 1 ) return _array;
    // 假設(shè)我取了數(shù)組中間的數(shù)作為基準(zhǔn)值号杏,得到他的下標(biāo), 我們使用~~來(lái)獲取值為floor時(shí)的整數(shù)部分婴氮,也可以使用Math.floor()來(lái)實(shí)現(xiàn)
    var _pivot_index = ~~( _array.length / 2 );
    //基準(zhǔn)值
    var _pivot = _array.splice(_pivot_index, 1)[0];
    // 我們需要兩個(gè)數(shù)組來(lái)存放大于小于基準(zhǔn)值的集合
    var _left = [] ,
        _right = [];
    for( var i = 0; i < _array.length; i++){
        // 這里進(jìn)行判斷,如果大于基準(zhǔn)值則放到右側(cè)數(shù)組馒索,反之則放到左側(cè)
        _array[i] > _pivot? _right.push( _array[i] ) : _left.push( _array[i] );
    }
    // 因?yàn)槲覀冏罱K要將拆分的數(shù)組連接起來(lái)莹妒,所以這里可以使用concat方法
    // 遞歸左邊的數(shù)組 連接基準(zhǔn)值 在鏈接遞歸右邊的數(shù)組
    return quickSort( _left ).concat( [ _pivot ], quickSort( _right ) );
}

至此我們就完成了快速排序的基本實(shí)現(xiàn)。
當(dāng)然此方法實(shí)現(xiàn)只能作為快速了解快排思路的例子绰上,實(shí)際運(yùn)用中旨怠,會(huì)帶來(lái)更大的內(nèi)存開銷等等,等待系列做完蜈块,將會(huì)逐一分析鉴腻,并提供更好的思路。

\color{#34a853}{感謝閱讀百揭!}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末爽哎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子器一,更是在濱河造成了極大的恐慌课锌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異渺贤,居然都是意外死亡雏胃,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門志鞍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)瞭亮,“玉大人,你說(shuō)我怎么就攤上這事固棚⊥臭妫” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵此洲,是天一觀的道長(zhǎng)厂汗。 經(jīng)常有香客問(wèn)我,道長(zhǎng)呜师,這世上最難降的妖魔是什么面徽? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮匣掸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘氮双。我一直安慰自己碰酝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布戴差。 她就那樣靜靜地躺著送爸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪暖释。 梳的紋絲不亂的頭發(fā)上袭厂,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音球匕,去河邊找鬼纹磺。 笑死,一個(gè)胖子當(dāng)著我的面吹牛亮曹,可吹牛的內(nèi)容都是我干的橄杨。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼照卦,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼式矫!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起役耕,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤采转,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后瞬痘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體故慈,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡板熊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惯悠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邻邮。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖克婶,靈堂內(nèi)的尸體忽然破棺而出筒严,到底是詐尸還是另有隱情,我是刑警寧澤情萤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布鸭蛙,位于F島的核電站,受9級(jí)特大地震影響筋岛,放射性物質(zhì)發(fā)生泄漏娶视。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一睁宰、第九天 我趴在偏房一處隱蔽的房頂上張望肪获。 院中可真熱鬧,春花似錦柒傻、人聲如沸孝赫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)青柄。三九已至,卻和暖如春预侯,著一層夾襖步出監(jiān)牢的瞬間致开,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工萎馅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留双戳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓糜芳,卻偏偏與公主長(zhǎng)得像拣技,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子耍目,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345