幾種初級排序演算法的總結
阿新 • • 發佈:2018-12-09
@TOC
幾種初級排序演算法的總結
排序就是將一組物件按照某種邏輯順序重新排列的過程。
在本文中我們使用的操作:
- 遍歷陣列
- 比較兩個物件(本文中所有程式碼示例中的less方法)
- 交換兩個物件 (本文中所有程式碼示例中的exch方法)
less 和 exch方法的原始碼:
private static boolean less(Comparable v, Comparable w) { return (v.compareTo(w) < 0); } private static void exch(Comparable[] a, int i, int j) { Comparable swap = a[i]; a[i] = a[j]; a[j] = swap; }
選擇排序
選擇排序的基本思路就是為每一個位置選擇對的物件:
- 選擇第一個位置;
- 從陣列中未被選擇的物件中選擇最小(或最大)的物件放入當前選擇的位置;
- 選擇下一個位置,並重復2直到所有位置都有物件;
程式碼示例:
public static void sort(Comparable[] a) { int n = a.length; for (int i = 0; i < n; i++) { //選擇位置的迴圈 int min = i; for (int j = i+1; j < n; j++) { //選擇剩餘物件中最小元素 if (less(a[j], a[min])) min = j; } exch(a, i, min); //交換位於選中位置上的元素和應該位於該位置的元素 } }
插入排序
插入排序的基本思路是將物件移動到已經有序的陣列中適當的位置,類似打撲克牌時將新接的牌插入適當位置:
- 選中當前陣列的第二個位置的物件;
- 比較當前選擇的物件與位於它前面的物件,根據比較結果,如果兩者現在相對位置是不對的,則互動它們,重複2.直到當前選擇的物件前面沒有元素或者,它和前面元素的相對位置是正確的;(一步一步往前挪)
- 選擇下一個位置的元素,並重復2直到陣列末尾;
示例程式碼:
public static void sort(Comparable[] a) { int n = a.length; for (int i = 1; i < n; i++) { //選擇需要挪動的物件 for (int j = i; j > 0; j--) { //一步一步往前挪 if(less(a[j], a[j-1])) //如果當前元素比前一個小,則交換位置 exch(a, j, j-1); else break; //已經挪到了對的位置,去挪下一個 } } }
希爾排序
希爾排序是一種基於插入排序的快速排序演算法;對於大規模的亂序陣列,插入排序會很慢,因為它只交換相鄰的物件,元素要一點一點的往前挪;希爾排序的基本思路是分別對間隔h的元素組成的陣列進行排序,使得原陣列h有序,然後逐步減小h,如下圖:
- 選取一個h;
- 對間隔h的物件組成的陣列進行插入排序;
- 減小h,重複2一直到h為1;
程式碼示例:
public static void sort(Comparable[] a) {
int n = a.length;
// 3x+1 increment sequence: 1, 4, 13, 40, 121, 364, 1093, ...
int h = 1;
while (h < n/3) h = 3*h + 1; //取一個大於等於陣列長度三分之一的h
while (h >= 1) {
// h-sort the array
for (int i = h; i < n; i++) { //使用插入排序對間隔h的物件組成的陣列進行排序
for (int j = i; j >= h && less(a[j], a[j-h]); j -= h) {
exch(a, j, j-h);
}
}
h /= 3; //按3的倍數減小h
}
}
效能與特性
- 穩定性:選擇排序的穩定性與具體實現有關,主要是判斷大小的條件對物件相等的時候的處理,在我們的實現中它是不穩定的,因為它會互動兩個相等的物件;插入排序是穩定的,因為挪動到相等元素時會停止;而基於插入排序的希爾排序卻是不穩定的,因為分組的過程中會間接打亂相等物件的相對位置。
- 空間:這三個演算法都是直接在原陣列上進行操作,並沒有申請額外空間,且無遞迴,所以空間複雜度為O(1)。
- 時間:選擇排序的時間複雜度為O($ N^2 N^2$) 之間,主要依賴於陣列的有序程度,陣列的有序程度越高,演算法的效率越好;希爾排序大概是O(NlogN) ,同樣和陣列的有序程度相關,不過通過分組使得隨機情況下演算法的效能比插入排序更好。
**一點猜想:**從選擇排序到希爾排序的效能變化,可能對應於演算法對已排序物件的資訊的利用程度的變化;比如一個數組中a、b、c是已經排好相對位置的元素,此時決定元素d的位置時,如果我們知道d>c,那麼可以推理得出d>b以及d>a,選擇排序對此類資訊利用的相對較少,而插入排序相對利用的多些。
參考資料
- 演算法(第四版)Robert Sedgewick 和 Kevin Wayne 著
- https://algs4.cs.princeton.edu/21elementary/ (文中所有程式碼來源)