1. 程式人生 > >排序算法系列:快速排序演算法

排序算法系列:快速排序演算法

概述

 在前面說到了兩個關於交換排序的演算法:氣泡排序與奇偶排序。
 本文就來說說交換排序的最後一拍:快速排序演算法。之所以說它是快速的原因,不是因為它比其他的排序演算法都要快。而是從實踐中證明了快速排序在平均效能上的確是比其他演算法要快一些,不然快速一說豈不是在亂說?
 本文就其原理、過程及實現幾個方面講解一下快速排序演算法。

目錄

快速排序

演算法原理

原理分析

快速排序(Quicksort)是對氣泡排序的一種改進。

 快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料變成有序序列。

原理圖

這裡寫圖片描述

演算法步驟

步驟

  1. 獲得待排序陣列a
  2. 選取一個合適的數字p(一般來說就選取陣列或是子陣列的第一個元素)作為排序基準
  3. 將待排序陣列a中比基準p小的放在p的左邊,比基準p大的放在p的右邊
    這裡寫圖片描述
  4. 從第3步獲得的兩個子陣列sub1跟sub2
  5. 判斷sub1或sub2中是否只有一個元素,如果只有一個元素則返回此元素,否則就將sub1(或是sub2)代回到第1步中繼續執行
  6. 具體過程可以參見下面的過程圖

過程演示圖

這裡寫圖片描述

邏輯實現

/*
     * 排序的核心演算法
     * 
     * @param array
     *      待排序陣列
     * @param startIndex
     *      開始位置
     * @param endIndex
     *      結束位置
     */
    private void sortCore(int[] array, int startIndex, int endIndex) {
        if (startIndex >= endIndex) {
            return
; } int boundary = boundary(array, startIndex, endIndex); sortCore(array, startIndex, boundary - 1); sortCore(array, boundary + 1, endIndex); } /* * 交換並返回分界點 * * @param array * 待排序陣列 * @param startIndex * 開始位置 * @param endIndex * 結束位置 * @return * 分界點 */ private int boundary(int[] array, int startIndex, int endIndex) { int standard = array[startIndex]; // 定義標準 int leftIndex = startIndex; // 左指標 int rightIndex = endIndex; // 右指標 while(leftIndex < rightIndex) { while(leftIndex < rightIndex && array[rightIndex] >= standard) { rightIndex--; } array[leftIndex] = array[rightIndex]; while(leftIndex < rightIndex && array[leftIndex] <= standard) { leftIndex++; } array[rightIndex] = array[leftIndex]; } array[leftIndex] = standard; return leftIndex; }

複雜度分析

排序方法 時間複雜度 空間複雜度 穩定性 複雜性
平均情況 最壞情況 最好情況
快速排序 O(nlog2n) O(n2) O(nlog2n) O(log2n) 不穩定 較複雜

 這裡我們可以做一些關於複雜度的推理。
 如果我們在選取基準p的時候,每次選取的都是當前陣列中最小的一個元素,那麼每次劃分都只是讓陣列中的元素少1(被篩選出來的那個元素當然有序),這樣一來就需要反覆遍歷陣列導致複雜度變成了O(n2)。
 如果我們在選取基準p的時候,每次選取的都是當前陣列中最中間的一個元素(是中位數,而不是元素位置上的中間),那麼每次劃分都把當前陣列劃分成了長度相等的兩個子陣列,這樣一來複雜度變成了O(nlog2n)。

番外

  1. 對於基準元素的選取,也可以採用隨機數選取的方式
  2. 如果要按照元素在位置上的中間來選取基準元素,還可以將中間位置上的元素與第一個元素進行對換

Ref

  • 《演算法導論 (第3版)》
  • 《程式設計珠璣 (第2版)》

GitHub原始碼下載

相關推薦

排序系列快速排序演算法

概述  在前面說到了兩個關於交換排序的演算法:氣泡排序與奇偶排序。  本文就來說說交換排序的最後一拍:快速排序演算法。之所以說它是快速的原因,不是因為它比其他的排序演算法都要快。而是從實踐中證明了快速排序在平均效能上的確是比其他演算法要快一些,不然快速一說豈

排序系列歸併排序演算法

概述 上一篇我們說了一個非常簡單的排序演算法——選擇排序。其複雜程式完全是冒泡級的,甚至比冒泡還要簡單。今天要說的是一個相對比較複雜的排序演算法——歸併排序。複雜的原因不僅在於歸併排序分成了兩個部分進行解決問題,而是在於,你需要一些演算法的思想支撐。 歸併排

排序系列Shell 排序演算法

概述 希爾排序(Shell Sort)是 D.L.Shell 於 1959 年提出來的一種排序演算法,在這之前排序演算法的時間複雜度基本都是 O(n2) 的,希爾排序演算法是突破這個時間複雜度的第一批演算法之一。希爾排序是一種插入排序演算法。 版權說

排序系列歸併排序(Merge sort)(C語言)

通俗理解:運用分而治之的思想,編寫遞迴函式,將大陣列排序轉化為小陣列排序,最後再將其合併。void merge_sort(int*p,int low,int high) { int mid = (low+high)/2; if (low <high) { m

排序系列奇偶排序演算法

概述   在上一篇中我們說到了氣泡排序的原理及實現詳解。氣泡排序是一種交換排序,本文還是接著上一講,說說另一種交換排序演算法——奇偶排序。 版權說明 目錄 奇偶排序演算法 奇偶排序實際上在多處理器環境中很有用,處

系列冒泡排序

冒泡 return 二層 單向 while 數組 代碼 示例 執行 一、基本思路 通過兩兩比較,然後交換雙方位置的一種排序方法。 二、示例代碼 $arr = array(1,4,2,6,3,8); for($i=0;$i<count($arr)-1;$i++){

PHP排序系列希爾排序

希爾排序 希爾排序(Shell Sort)是插入排序的一種。也稱縮小增量排序,是直接插入排序演算法的一種更高效的改進版本。希爾排序是非穩定排序演算法。 原理 先將整個待排元素序列分割成若干個子序列(由相隔某個“增量(gap)”的元素組成的)分別進行直接

[閉目洞察系列之一]快速排序

這是第一篇關於演算法的部落格, 我本人對演算法沒什麼深刻見解, 此處只是對別人部落格的再整理, 用自己理解的方式進行表述一遍, 一方面加深印象, 另一方面做知識沉澱,供他日食用。 廢話到此為止, 下面

C語言實現TOP K系列快速排序實現

TOP K演算法的實現有很多種方式,其中類似於快排的實現是非常棒的,堆的實現也是非常好的,其中就是關於快排的實現會得到一個TOP K的集合,而這個集合不一定保證裡面的資料都是有序的。 下面就獻上TOP

簡單系列快速/冒泡兩則

mil 小例子 turn int 設計 pan 問題 體會 理解 工作較忙,沒辦法抽出時間專心攻克《Go語言編程》,隨著了解的更多,越發體會出這本書中小例子的精巧。 掌握這些小例子,就可以完成Go基礎的全面掌握 最近抽出時間專心敲這些例子。但是發現一些問題,在設計上,許大大

排序排序

family getch 電子郵箱 -s class csharp soft n) 郵件   在我們的生活的這個世界到處都是被排序過的東西。站隊的時候會按照身高排序,考試的名次需要按照分數排序,網上購物的時候會按照價格排序,電子郵箱中的郵件按照時間排序……可以說排序無處不在

排序入門之快速排序(java實現)

大小 ava 相對 其余 時間 個數 技術分享 算法 元素交換   快速排序也是一種分治的排序算法。快速排序和歸並排序是互補的:歸並排序將數組分成兩個子數組分別排序,並將有序的子數組歸並以將整個數組排序,會需要一個額外的數組;而快速排序的排序方式是當兩個子數組都有序

(九)數據結構之簡單排序實現冒泡排序、插入排序和選擇排序

html lan 獎章 tmx 4tb wot 數據結構 lec get d59FG8075P7伊http://www.zcool.com.cn/collection/ZMTg2NTU2NjQ=.html 312V畏蝗淤ZP哦睬http://www.zcool.com.c

排序積累(3)-----快速排序

快速排序 函數 一個數 rand sig 圖片 大於 void oid 一. 快速排序思路   1. 快速排序首先在所需要排序的數據中隨機地選出一個數作為閥值,並把這個數(也就是這個閥值)與原來數據中最後的一個數交換,到了這步,數據中最後的一個數就是這個閥值了。   2.

排序系列---希爾排序(C++)

希爾排序:明白它的原理之後,希爾演算法其實就是更加先進的一種插入排序,之前的直接插入排序是逐個比較,找到合適的位置就插入,希爾排序是跳躍式的插入,拿當前的數和n(自己定義的跳躍數)個之前的數比較,較小的數位置提前。希爾演算法相當於先把整個序列分割成幾塊序列,塊和

八大排序總結(五)快速排序

con 遞歸調用 結果 width 算法總結 調用 小數 排序算法總結 png 目的:掌握 快速排序 的 基本思想與過程、代碼實現、時間復雜度 1、基本思想與過程:(分治思想,挖坑填數)   (1)從數列中選擇一個數作為key值;   (2)將比這個數小的數全部放在它的左邊

排序系列——八大排序演算法對比分析

本系列最後一篇,綜合分析下前面介紹的八種排序演算法的效率,以及各自的適用情況。 下面先看看八種排序演算法的時間複雜度表格: 圖中八種排序被分成了兩組,一組時間複雜度為O(n^2),另一組相對高效些。 下面先對第一組O(n^2)的四種排序演算法進行對比,

資料結構與系列十(排序演算法概述)

1.引子 1.1.為什麼要學習資料結構與演算法? 有人說,資料結構與演算法,計算機網路,與作業系統都一樣,脫離日常開發,除了面試這輩子可能都用不到呀! 有人說,我是做業務開發的,只要熟練API,熟練框架,熟練各種中介軟體,寫的程式碼不也能“飛”起來嗎? 於是問題來了:為什麼還要學習資料結構與演算法呢? #理

數據結構與系列研究九——排序的一些探討

停止 不同 位置 集合 完全 設置 img com 去除 四種排序 一.實驗內容 輸入20個整數,分別用希爾排序、快速排序、堆排序和歸並排序實現由小到大排序並輸出排序結果。二.關鍵數據結構與核心算法 關鍵數據結構:由於是排序為了簡單起見,選用線性表中的數組作為存

中的快速排序 quicksort

wide div 對比 nal optimize rate fse incr mce 快速排序之所以比較快,是因為相比冒泡排序,每次交換是跳躍式的。每次排序的時候設置一個基準點,將小於等於基準點的數全部放到基準點的左邊,將大於等於基準點的數全 部放到基準點的右邊。這樣在每次