javascript 快速排序

快速排序由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

如今交換哨兵 i 和哨兵 j 所指向的元素的值。交換以後的序列以下:

6 1 2 (5) 9 3 4 (7) 10 8cdn

到此,第一次交換結束。接下來開始哨兵j繼續向左挪動(再友情提醒,每次必須是哨兵j先出發)。他發現了4(比基準數6要小,知足要求)以後停了下來。哨兵i也繼續向右挪動的,他發現了9(比基準數6要大,知足要求)以後停了下來。此時再次進行交換,交換以後的序列以下:

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

到此第一輪「探測」真正結束。此時以基準數6爲分界點,6左邊的數都小於等於6,6右邊的數都大於等於6。回顧一下剛纔的過程,其實哨兵j的使命就是要找小於基準數的數,而哨兵i的使命就是要找大於基準數的數,直到i和j碰頭爲止。

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

到此,排序徹底結束。細心的同窗可能已經發現,快速排序的每一輪處理其實就是將這一輪的基準數歸位,直到全部的數都歸位爲止,排序就結束了。下面上個霸氣的圖來描述下整個算法的處理過程。

動畫演示

如今咱們經過js語言實現快速排序

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/…

相關文章
相關標籤/搜索