一看就懂的快速排序

概念

快速排序?qū)儆诮粨Q排序,主要步驟是使用基準(zhǔn)元素進(jìn)行比較许师,把小于基準(zhǔn)元素的移動到一邊微渠,大于基準(zhǔn)元素的移動到另一邊逞盆。從而把數(shù)組分成兩部分,然后再從這兩部分中選取出基準(zhǔn)元素续扔,重復(fù)上面的步驟纱昧。過程如下:

紫色:基準(zhǔn)元素
綠色:大于基準(zhǔn)元素
黃色:小于基準(zhǔn)元素

file

這種思路叫做分治法识脆。

基準(zhǔn)元素

基準(zhǔn)元素的選取可隨機選取灼捂。下面使用中我會使用第一位的元素作為基準(zhǔn)元素悉稠。

排序過程

排序拆分過程如下圖:

紫色為基準(zhǔn)元素的猛,(每一輪都重新選蓉宰稹)
綠色為其他元素

第一輪

file

第二輪

file

第三輪

file

如上圖所示:
若元素個數(shù)為n,因為排序過程中需要和全部元素都比較一遍躏哩,所以時間復(fù)雜度為O(n)震庭,
而平均情況下排序輪次需要logn輪你雌,因此快速排序的平均時間復(fù)雜度為O(nlogn)拨拓。

排序的實現(xiàn)方法

實現(xiàn)方法有雙邊循環(huán)法和單邊循環(huán)法

雙邊循環(huán)法

首選選取基準(zhǔn)元素(pivot)4渣磷,并設(shè)置指針left和right醋界,指向數(shù)組最左和最右兩個元素提完,如下:

file

第一次循環(huán)逐样,先從right指針指向的數(shù)據(jù)(rightData)開始和基準(zhǔn)元素比較
若 rightData >= pivot打肝,則right指針向左移動粗梭,若 rightData < pivot断医,則right指針不移動,切換到left指針
left指針指向數(shù)據(jù)(leftData)與基準(zhǔn)元素比較酷宵,若 leftData <= pivot浇垦,則left指針向右移動男韧,若 leftData > pivot默垄,交換left和right指向的元素口锭。

第一輪指針移動完后介杆,得到如下結(jié)構(gòu):

file

然后 left和right指向的元素進(jìn)行交換:

file

第一輪循環(huán)結(jié)束,重新切換到right指針赴背,重復(fù)上述步驟凰荚。
第二輪循環(huán)后便瑟,得:

file

第三輪循環(huán)后胳徽,得:

file

第四輪循環(huán)后养盗,得:

file

判斷到left和right指針指向同一個元素往核,指針停止移動聂儒,使pivot和指針元素進(jìn)行交換衩婚,得:

file

宣告該輪循環(huán)結(jié)束效斑,并根據(jù)Pivot元素切分為兩部分缓屠,這兩部分的數(shù)組再根據(jù)上述步驟進(jìn)行操作敌完。

實現(xiàn)代碼

public class DoubleSort {
    public static void quickSort(int[] arr, int startIndex, int endIndex) {

        //遞歸結(jié)束條件
        if (startIndex >= endIndex) {
            return;
        }

        // 基準(zhǔn)元素位置
        int pivotIndex = partition(arr, startIndex, endIndex);

        // 根據(jù)基準(zhǔn)元素,分成兩部分進(jìn)行遞歸排序
        quickSort(arr, startIndex, pivotIndex - 1);
        quickSort(arr, pivotIndex + 1, endIndex);
    }

    public static int partition(int[] arr, int startIndex, int endIndex) {
        // 取第一個元素為基準(zhǔn)元素什湘,也可以隨機抽取
        int pivot = arr[startIndex];
        int left = startIndex;
        int right = endIndex;

        while (left != right) {
            // 控制right指針比較并左移
            while (left < right && arr[right] >= pivot) {
                right--;
            }

            // 控制left指針比較并右移
            while (left < right && arr[left] <= pivot) {
                left++;
            }

            // 交換left和right指針?biāo)赶虻脑?            if (left < right) {
                int temp = arr[right];
                arr[right] = arr[left];
                arr[left] = temp;
            }
        }

        arr[startIndex] = arr[left];
        arr[left] = pivot;
        return left;
    }

    public static void main(String[] args) {
        int[] arr = new int[]{4, 7, 6, 5, 3, 2, 8, 1};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
}

單邊循環(huán)法

雙邊循環(huán)法從數(shù)組的兩邊比較并交換元素禽炬,而單邊循環(huán)法則從數(shù)組的一邊遍歷,一直往后比較和交換,實現(xiàn)起來更加的簡單热幔。
過程如下:

首先也是選取基準(zhǔn)元素pivot(可以隨機選擇)
設(shè)置一個mark指針指向數(shù)組的起始位置绎巨,代表小于基準(zhǔn)元素的區(qū)域邊界(不理解的就把它理解成是等會用來交換元素的就好了)

原始數(shù)組如下:

file

從基準(zhǔn)元素下一位開始遍歷數(shù)組
如果該元素大于基準(zhǔn)元素场勤,繼續(xù)往下遍歷
如果該元素小于基準(zhǔn)元素歼跟,mark指針往右移哈街,因為小于基準(zhǔn)元素的區(qū)域邊界增大了1(即小于基準(zhǔn)元素的多了1位),所以mark就 +1她倘,并且該元素和mark指向元素進(jìn)行交換硬梁。

遍歷到元素3時胞得,因為3 < 4懒震,所以mark右移

file

然后交換元素

file

然后就繼續(xù)遍歷个扰,根據(jù)上面的步驟進(jìn)行判斷递宅,后面的過程就不寫了苍狰。

實現(xiàn)代碼

public class SingleSort {
    public static void quickSort(int[] arr, int startIndex, int endIndex) {

        //遞歸結(jié)束條件
        if (startIndex >= endIndex) {
            return;
        }

        // 基準(zhǔn)元素位置
        int pivotIndex = partition(arr, startIndex, endIndex);

        // 根據(jù)基準(zhǔn)元素淋昭,分成兩部分進(jìn)行遞歸排序
        quickSort(arr, startIndex, pivotIndex - 1);
        quickSort(arr, pivotIndex + 1, endIndex);
    }

    /**
     * 分治(單邊循環(huán)法)
     * @param arr
     * @param startIndex
     * @param endIndex
     * @return
     */
    public static int partition(int[] arr, int startIndex, int endIndex) {
        // 取第一個元素為基準(zhǔn)元素翔忽,也可以隨機抽取
        int pivot = arr[startIndex];
        int mark = startIndex;

        for(int i = startIndex + 1; i< arr.length; i++) {
            if (pivot < arr[i]) {
                continue;
            }

            mark ++;
            int temp = arr[mark];
            arr[mark] = arr[i];
            arr[i] = temp;
        }
        arr[startIndex] = arr[mark];
        arr[mark] = pivot;
        return mark;
    }

    public static void main(String[] args) {
        int[] arr = new int[]{4, 7, 6, 5, 3, 2, 8, 1};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
}

總結(jié)

本人也是初次接觸算法,慢慢的去理解算法的思路和實現(xiàn)過程后胡野,真是為自己以往寫的算法感到羞愧。該文章也是為了加深自己對快排算法的印象龙巨,若文章有不足之處旨别,懇請各位在下方留言補充耘眨。感謝各位的閱讀。Thanks?(?ω?)?胆屿。

參考資料:《小灰的算法之旅》 第四章非迹。

個人博客網(wǎng)址: https://colablog.cn/

如果我的文章幫助到您,可以關(guān)注我的微信公眾號憎兽,第一時間分享文章給您

微信公眾號
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市痹栖,隨后出現(xiàn)的幾起案子揪阿,更是在濱河造成了極大的恐慌,老刑警劉巖吴裤,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件麦牺,死亡現(xiàn)場離奇詭異剖膳,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門枕荞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來躏精,“玉大人矗烛,你說我怎么就攤上這事瞭吃』林迹” “怎么了霹陡?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵烹棉,是天一觀的道長浆洗。 經(jīng)常有香客問我,道長泣崩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任凯沪,我火速辦了婚禮妨马,結(jié)果婚禮上烘跺,老公的妹妹穿的比我還像新娘滤淳。我一直安慰自己砌左,他們只是感情好汇歹,可當(dāng)我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布派歌。 她就那樣靜靜地躺著痰哨,像睡著了一般作谭。 火紅的嫁衣襯著肌膚如雪折欠。 梳的紋絲不亂的頭發(fā)上锐秦,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天羊赵,我揣著相機與錄音昧捷,去河邊找鬼靡挥。 笑死,一個胖子當(dāng)著我的面吹牛跋破,可吹牛的內(nèi)容都是我干的簸淀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼毒返,長吁一口氣:“原來是場噩夢啊……” “哼租幕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拧簸,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤劲绪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后盆赤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體珠叔,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年弟劲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡台囱,死狀恐怖咱娶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情琼了,我是刑警寧澤昧诱,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布妆丘,位于F島的核電站鱼填,受9級特大地震影響愤惰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一瞪醋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谅河,春花似錦诸典、人聲如沸必尼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至之景,卻和暖如春轻纪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背掂僵。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工坤塞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓熬词,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嚎幸。 傳聞我的和親對象是個殘疾皇子田篇,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 冒泡排序 冒泡排序相對來說是較為簡單的一種排序教沾,它的思想就是在每一次循環(huán)中比較相鄰的兩個數(shù)巡语,通過交換的方式枢赔,將最小...
    陌上疏影涼閱讀 584評論 0 3
  • 本文首發(fā)于我的個人博客:尾尾部落 排序算法是最經(jīng)典的算法知識峦嗤。因為其實現(xiàn)代碼短,應(yīng)該廣糠睡,在面試中經(jīng)常會問到排序算法...
    繁著閱讀 4,572評論 3 119
  • 1.實現(xiàn)快速排序算法 問題描述給定一個無序數(shù)組int[ ] a油挥,使用快速排序算法進(jìn)行排序。 解題思路對于快速排序,...
    孫樹沖閱讀 1,320評論 0 1
  • 最近在看數(shù)據(jù)結(jié)構(gòu)盲链,研究了一下常用的幾種排序方法:1.冒泡排序,2.選擇排序藤违,3.插入排序,4.希爾排序犹菱,5.快速排...
    wo883721閱讀 1,487評論 0 4
  • 好像在很久以前就知道了長投龙亲,但一直是在遠(yuǎn)遠(yuǎn)的觀望鳄炉,并沒有近距離的接觸拂盯。 直到2017年9月21日的晚上看到14天理...
    妮妮_50e3閱讀 230評論 0 0