快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:經過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的全部數據都比另一部分的全部數據都要小,而後再按此方法對這兩部分數據分別進行快速排序,整個排序過程能夠遞歸進行,以此達到整個數據變成有序序列算法
有沒有既不浪費空間又能夠快一點的排序算法呢?那就是「快速排序」啦!光聽這個名字是否是就以爲很高端呢。數組
假設咱們如今對「6 1 2 7 9 3 4 5 10 8」這個10個數進行排序。首先在這個序列中隨便找一個數做爲基準數(不要被這個名詞嚇到了,就是一個用來參照的數,待會你就知道它用來作啥的了)。爲了方便,就讓第一個數6做爲基準數吧。接下來,須要將這個序列中全部比基準數大的數放在6的右邊,比基準數小的數放在6的左邊,相似下面這種排列:動畫
3 1 2 5 4 6 9 7 10 8ui
在初始狀態下,數字6在序列的第1位。咱們的目標是將6挪到序列中間的某個位置,假設這個位置是k。如今就須要尋找這個k,而且以第k位爲分界點,左邊的數都小於等於6,右邊的數都大於等於6。想想,你有辦法能夠作到這點嗎?spa
方法其實很簡單:分別從初始序列「6 1 2 7 9 3 4 5 10 8」兩端開始「探測」。先從右往左找一個小於6的數,再從左往右找一個大於6的數,而後交換他們。這裏能夠用兩個變量i和j,分別指向序列最左邊和最右邊。咱們爲這兩個變量起個好聽的名字「哨兵i」和「哨兵j」。剛開始的時候讓哨兵i指向序列的最左邊(即i=1),指向數字6。讓哨兵j指向序列的最右邊(即=10),指向數字。3d
首先哨兵j開始出動。由於此處設置的基準數是最左邊的數,因此須要讓哨兵j先出動,這一點很是重要(請本身想想爲何)。哨兵j一步一步地向左挪動(即j--),直到找到一個小於6的數停下來。接下來哨兵i再一步一步向右挪動(即i++),直到找到一個數大於6的數停下來。最後哨兵j停在了數字5面前,哨兵i停在了數字7面前。code
6 1 2 (5) 9 3 4 (7) 10 8cdn
6 1 2 5 (4) 3 (9) 7 10 8htm
第二次交換結束,「探測」繼續。哨兵j繼續向左挪動,他發現了3(比基準數6要小,知足要求)以後又停了下來。哨兵i繼續向右移動,糟啦!此時哨兵i和哨兵j相遇了,哨兵i和哨兵j都走到3面前。說明此時「探測」結束。咱們將基準數6和3進行交換。交換以後的序列以下:blog
(3) 1 2 5 4 (6) 9 7 10 8
OK,解釋完畢。如今基準數6已經歸位,它正好處在序列的第6位。此時咱們已經將原來的序列,以6爲分界點拆分紅了兩個序列,左邊的序列是「3 1 2 5 4」,右邊的序列是「9 7 10 8」。接下來還須要分別處理這兩個序列。由於6左邊和右邊的序列目前都仍是很混亂的。不過沒關係,咱們已經掌握了方法,接下來只要模擬剛纔的方法分別處理6左邊和右邊的序列便可。如今先來處理6左邊的序列現吧。
左邊的序列是「3 1 2 5 4」。請將這個序列以3爲基準數進行調整,使得3左邊的數都小於等於3,3右邊的數都大於等於3。好了開始動筆吧
若是你模擬的沒有錯,調整完畢以後的序列的順序應該是:
2 1 3 5 4
OK,如今3已經歸位。接下來須要處理3左邊的序列「2 1」和右邊的序列「5 4」。對序列「2 1」以2爲基準數進行調整,處理完畢以後的序列爲「1 2」,到此2已經歸位。序列「1」只有一個數,也不須要進行任何處理。至此咱們對序列「2 1」已所有處理完畢,獲得序列是「1 2」。序列「5 4」的處理也仿照此方法,最後獲得的序列以下: 1 2 3 4 5 6 9 7 10 8
對於序列「9 7 10 8」也模擬剛纔的過程,直到不可拆分出新的子序列爲止。最終將會獲得這樣的序列,以下
1 2 3 4 5 6 7 8 9 10
到此,排序徹底結束。細心的同窗可能已經發現,快速排序的每一輪處理其實就是將這一輪的基準數歸位,直到全部的數都歸位爲止,排序就結束了。下面上個霸氣的圖來描述下整個算法的處理過程。
function quickSort2(arr, begin, end) {
//arr表明此時要進行排序的數組,begin表明基準值在數組中的位數,若是以上面爲例,
//基準值爲6,則begin爲0,end表明數組最後一位值的序數(arr.length)
//若是左右兩個值移動到重合位置,則結束
if (begin >= end) {
return;
}
//選基準值
//leader即爲上面的第一次比較時的基準值6
var leader = arr[begin];
var left = begin;
var right = end;
//沒有重合,此時right在left的右邊進行循環
while(left < right) {
//首先右邊和leader比
while (left < right) {
if (arr[right] < leader) {
arr[left] = arr[right];
left += 1;
break;
} else {
//若是右邊的值不小於基準值,則向左移動一位
right -= 1;
}
}
while (left < right) {
if (arr[left] > leader) {
arr[right] = arr[left];
//若是左邊的值不大於基準值,則向右移動一位
right -= 1;
break;
} else {
left += 1;
}
}
}
arr[left] = leader;
quickSort2(arr, begin, left - 1);
quickSort2(arr, left + 1, end);
}
quickSort2(arr, 0, arr.length - 1);
複製代碼
坐在馬桶上看算法:developer.51cto.com/art/201403/…