常見排序演算法時間複雜度、空間複雜度、穩定性總結
排序演算法分類
排序演算法比較表格
排序演算法 | 平均時間複雜度 | 最壞時間複雜度 | 空間複雜度 | 是否穩定 |
---|---|---|---|---|
氣泡排序 | O(n2) | O(n2) | O(1) | 是 |
選擇排序 | O(n2) | O(n2) | O(1) | 不是 |
直接插入排序 | O(n2) | O(n2) | O(1) | 是 |
歸併排序 | O(nlogn) | O(nlogn) | O(n) | 是 |
快速排序 | O(nlogn) | O(n2) | O(logn) | 不是 |
堆排序 | O(nlogn) | O(nlogn) | O(1) | 不是 |
希爾排序 | O(nlogn) | O(ns) | O(1) | 不是 |
計數排序 | O(n+k) | O(n+k) | O(n+k) | 是 |
基數排序 | O(N∗M)O(N∗M) | O(N∗M) | O(M) | 是 |
注:
1 歸併排序可以通過手搖演算法將空間複雜度降到O(1),但是時間複雜度會提高。
2 基數排序時間複雜度為O(N*M),其中N為資料個數,M為資料位數。
輔助記憶
- 時間複雜度記憶-
- 冒泡、選擇、直接 排序需要兩個for迴圈,每次只關注一個元素,平均時間複雜度為O(n2)(一遍找元素O(n)O(n),一遍找位置O(n)O(n))
- 快速、歸併、希爾、堆基於二分思想,log以2為底,平均時間複雜度為O(nlogn)(一遍找元素O(n),一遍找位置O(logn))
- 穩定性記憶-“快希選堆”(快犧牲穩定性)
- 排序演算法的穩定性:排序前後相同元素的相對位置不變,則稱排序演算法是穩定的;否則排序演算法是不穩定的。
原理理解
1 氣泡排序
1.1 過程
氣泡排序從小到大排序:一開始交換的區間為0~N-1,將第1個數和第2個數進行比較,前面大於後面,交換兩個數,否則不交換。再比較第2個數和第三個數,前面大於後面,交換兩個數否則不交換。依次進行,最大的數會放在陣列最後的位置。然後將範圍變為0~N-2,陣列第二大的數會放在陣列倒數第二的位置。依次進行整個交換過程,最後範圍只剩一個數時陣列即為有序。
1.2 動圖
1.3核心程式碼
2 選擇排序
2.1 過程
選擇排序從小到大排序:一開始從0~n-1區間上選擇一個最小值,將其放在位置0上,然後在1~n-1範圍上選取最小值放在位置1上。重複過程直到剩下最後一個元素,陣列即為有序。
2.2 動圖
2.3核心程式碼
3 插入排序
3.1 過程
插入排序從小到大排序:首先位置1上的數和位置0上的數進行比較,如果位置1上的數大於位置0上的數,將位置0上的數向後移一位,將1插入到0位置,否則不處理。位置k上的數和之前的數依次進行比較,如果位置K上的數更大,將之前的數向後移位,最後將位置k上的數插入不滿足條件點,反之不處理。
3.2 動圖
3.3核心程式碼
4 歸併排序
4.1 過程
歸併排序從小到大排序:首先讓陣列中的每一個數單獨成為長度為1的區間,然後兩兩一組有序合併,得到長度為2的有序區間,依次進行,直到合成整個區間。
4.2 動圖
4.3核心程式碼
·遞迴實現
·迭代實現
5 快速排序
5.1 過程
快速排序從小到大排序:在陣列中隨機選一個數(預設陣列首個元素),陣列中小於等於此數的放在左邊,大於此數的放在右邊,再對陣列兩邊遞迴呼叫快速排序,重複這個過程。
5.2 動圖
5.3核心程式碼
6 堆排序
6.1 過程
堆排序從小到大排序:首先將陣列元素建成大小為n的大頂堆,堆頂(陣列第一個元素)是所有元素中的最大值,將堆頂元素和陣列最後一個元素進行交換,再將除了最後一個數的n-1個元素建立成大頂堆,再將最大元素和陣列倒數第二個元素進行交換,重複直至堆大小減為1。
-
注:完全二叉樹
假設二叉樹深度為n,除了第n層外,n-1層節點都有兩個孩子,第n層節點連續從左到右。如下圖 -
注:大頂堆
大頂堆是具有以下性質的完全二叉樹:每個節點的值都大於或等於其左右孩子節點的值。
即,根節點是堆中最大的值,按照層序遍歷給節點從1開始編號,則節點之間滿足如下關係:
(1<=i<=n/2)
6.2 動圖
6.3 核心程式碼(函式)
注意!!!陣列從1開始,1~n。
7 希爾排序
7.1 過程
希爾排序是插入排序改良的演算法,希爾排序步長從大到小調整,第一次迴圈後面元素逐個和前面元素按間隔步長進行比較並交換,直至步長為1,步長選擇是關鍵。
7.2 動圖
7.3 核心程式(函式)
8 桶排序(基數排序和基數排序的思想)
8.1 過程
桶排序是計數排序的變種,把計數排序中相鄰的m個”小桶”放到一個”大桶”中,在分完桶後,對每個桶進行排序(一般用快排),然後合併成最後的結果。
8.2 圖解
8.3 核心程式
9 計數排序
9.1 過程
演算法的步驟如下:
- 找出待排序的陣列中最大和最小的元素
- 統計陣列中每個值為i的元素出現的次數,存入陣列C的第i項
- 對所有的計數累加(從C中的第一個元素開始,每一項和前一項相加)
- 反向填充目標陣列:將每個元素i放在新陣列的第C(i)項,每放一個元素就將C(i)減去1
9.2 圖解
9.3核心程式碼
10 基數排序
10.1 過程
基數排序是基於資料位數的一種排序演算法。
它有兩種演算法
①LSD–Least Significant Digit first 從低位(個位)向高位排。
②MSD– Most Significant Digit first 從高位向低位(個位)排。
時間複雜度O(N*最大位數)。
空間複雜度O(N)。
10.2 圖解
對a[n]按照個位0~9進行桶排序:
對b[n]進行累加得到c[n],用於b[n]中重複元素計數
!!!b[n]中的元素為temp中的位置!!!跳躍的用++補上:
temp陣列為排序後的陣列,寫回a[n]。temp為按順序倒出桶中的資料(聯合b[n],c[n],a[n]得到),重複元素按順序輸出:
10.3核心程式碼