刷抖音?不如來學算法,幾分鐘搞定一個快速排序

快速排序是一種高效的排序算法,也是面試常考的一種算法,大多數人畏懼和逃避算法,不是由於算法有多難,而是沒有找到合適的老師,簡單說就是沒有通俗易懂的文章,致使學習者越看越懵,看完即忘的現象。今天我想嘗試作一個「好老師」,用通俗易懂的方式講解一下什麼是快速排序。java

圖解思想

不少文章,上來就用某種語言,開始啪啦啪啦寫代碼,不熟悉該種語言的學者,一臉矇蔽,又是一篇水文。或者跟着代碼看了一下,感受會了,關掉網頁,腦子:what???我剛纔看了啥?面試

算法與編程語言無關,它是一種思想,理解了思想,編程語言只是一種實現方式。算法

OK,來看看快速排序的思想編程

假設如今有一個亂序的數組:數組

5 3 6 1 4 8 2 7
複製代碼

快速排序核心思想:編程語言

隨意找一個目標值,放在數組的某個下標,使得該下標的左側數值都小於目標值,右側數值都大於目標值學習

隨意選一個目標值,假如就數組的第一個數值 5,如今須要將 5 移動到數組的某個下標 K 上,而且以 K 爲臨界點,左邊的數小於 5 ,右邊的數大於 5 ,該怎麼操做?ui

使用一種二分交換的思想,以什麼分?如下標 K 分。須要解決2個問題,如何交換數值,如何肯定下標 Kspa

如何交換?

模擬兩我的,從數組 5 3 6 1 4 8 2 7 兩邊開始探測,先從右往左開始找一個小於5的數,再從左往右找一個大於5的數,而後交換數據,交換完成繼續探測,直到兩我的相遇code

模擬的兩我的暫且稱它們爲:"探子j""探子i"

開始時,"探子j" 站在 右邊"探子i" 站在 左邊

在這裏插入圖片描述
因爲咱們選了最左邊的數爲 基準數,因此要從右邊的 "探子j" 先出發,這個很重要(緣由等你看完整個思路,本身模擬從左邊開始試試就知道哪裏出錯了) "探子j" 一步步向左移動(j- -)尋找小於 5 的數字,找到 2 知足,停下來。再出動 "探子i" 一步步向右移動(i++)尋找大於5的數字,找到 6 知足,停下來。此時 "探子i" 停在6上, "探子j" 停在2上,而後交換 i 和 j 的數值
在這裏插入圖片描述
到這裏完成了第一次交換,數組變化:

5 3 6 1 4 8 2 7 => 5 3 2 1 4 8 6 7

在現有的位置上繼續探測,仍是從 "探子j" 開始(強調,每次都是從探子j開始),繼續向左移動(j- -),找到 4 知足,停下來;而後 "探子i" 開始繼續往右尋找,走到 4 沒有找到大於 5 的數字兩我的就相遇了。(若是相遇以前能找到知足的數值,則依舊交換這兩個值)

在這裏插入圖片描述

如何肯定下標 K

當兩個探子相遇的下標位置,就是下標 K,此時將下標 K 數值與以前選擇的 基準數 相互交換,實現 K 的左邊都小於基準數,右邊大於基準數

在這裏插入圖片描述
到這一步,咱們肯定了臨界點 K,而且實現 K 左邊的數小於 基準數 ,右邊的數大於 基準數。獲得數組:

4 3 2 1 5 8 6 7

以 K (5) 作分界點,將數組分爲兩個部分,而後將左右兩邊的子數組在執行上述操做,最終將整個數組完成排序

OK,以上就是快速排序的基本思想,應該能夠理解吧。

擼碼實現算法

理解了思想,就按照這算法的思想一步步寫代碼就好了,本人熟悉java,就用java做爲編程語言擼一遍

/** * 快速排序 * * @param array 目標數組 * @param left 數組最左下標值 * @param right 數組最右下標值 */
    public static void quickSort(int[] array, int left, int right) {

        //防止數組越界(這一步最後再回來理解)
        if (left >= right) return;

        int base = array[left];//基準數
        int i = left, j = right;//左探子i,右探子j
        int temp;//用於交換的臨時變量

        while (i != j) {//兩個探子相遇前

            //找出小於 基準數 的下標,當大於等於 基準數 的時候,探子j 向左移動便可(j--)
            while (array[j] >= base && i < j) {
                j--;
            }

            //找出大於 基準數 的下標,當小於等於 基準數 的時候,探子i 向右移動便可(i++)
            while (array[i] <= base && i < j) {
                i++;
            }

            //通過上面兩個循環以後,探子j,探子i 都會停在符合條件的值的下標上面,而後就能夠進行交換值啦
            if (i < j) {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }

        //通過上面的循環以後會觸發 i=j 的條件(即兩個探子相遇),此時將基準值的數與i或者j(隨便哪一個都同樣)下標的值交換,完成一次交換探測
        array[left] = array[i];//基準值的位置
        array[i] = base;//基準值

        //完成交換以後再對左右兩邊的子數組進行遞歸調用走上面的方法,完成整個數組的排序
        quickSort(array, left, i - 1);//左邊
        quickSort(array, i + 1, right); //右邊
    }
複製代碼

讀註釋!讀註釋!讀註釋!而後就是,使用快排算法排序數組

int[] array = new int[]{5, 3, 6, 1, 4, 8, 2, 7};
        quickSort(array, 0, array.length - 1);//快速排序
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");//打印排序後的數組
        }
複製代碼

結果輸出

1 2 3 4 5 6 7 8 
複製代碼
相關文章
相關標籤/搜索