插入排序
對於插入排序,大部分資料都是使用撲克牌整理作爲例子來引入的,我們打牌都是一張一張摸牌的,每摸到一張牌就會跟手裏所有的牌比較來選擇合適的位置插入這張牌,這也就是直接插入排序的中心思想,我們先來看下動圖:
相信大家看完動圖以後大概知道了插入排序的實現思路了。那麼我們就來說下插入排序的思想。
插入排序的思想:
- 從第一個元素開始,該元素可以認爲已經被排序
- 取出下一個元素,在已經排序的元素序列中從後向前掃描
- 如果該元素(已排序)大於新元素,將該元素移到下一位置
- 重複步驟 3,直到找到已排序的元素小於或者等於新元素的位置
- 將新元素插入到該位置後
重複步驟 2~5
理解上述思想其實並不難,我們來看看用 Java 怎麼實現:
public class Test09 {
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
private static void printArr(int[] arr) {
for (int anArr : arr) {
System.out.print(anArr + " ");
}
}
private static void insertionSort(int[] arr) {
if (arr == null)
return;
int j;
int temp;
for (int i = 1; i < arr.length; i++) {
// 設置哨兵,拿出待插入的值
temp = arr[i];
j = i;
// 然後尋找正確插入的位置
while (j > 0 && arr[j - 1] > temp) {
arr[j] = arr[j - 1];
j--;
}
arr[j] = temp;
}
}
public static void main(String[] args) {
int[] arr = {6, 4, 2, 1, 8, 3, 7, 9, 5};
insertionSort(arr);
printArr(arr);
}
}
插入排序的時間複雜度和空間複雜度分析
對於插入的時間複雜度和空間複雜度,通過代碼就可以看出跟選擇和冒泡來說沒什麼區別,同屬於 O(n²) 級別的時間複雜度算法 ,只是遍歷方式有原來的 n n-1 n-2 … 1,變成了 1 2 3 … n 了。最終得到時間複雜度都是 n(n-1)/2。
對於穩定性來說,插入排序和冒泡一樣,並不會改變原有的元素之間的順序,如果遇見一個與插入元素相等的,那麼把待插入的元素放在相等元素的後面。所以,相等元素的前後順序沒有改變,從原無序序列出去的順序仍是排好序後的順序,所以插入排序是穩定的。
對於插入排序這裏說一個非常重要的一點就是:由於這個算法可以提前終止內層比較( arr[j-1] > arr[j])所以這個排序算法很有用!因此對於一些 NlogN 級別的算法,後邊的歸併和快速都屬於這個級別的,算法來說對於 n 小於一定級別的時候(Array.sort 中使用的是47)都可以用插入算法來優化,另外對於近乎有序的數組來說這個提前終止的方式就顯得更加又有優勢了。
插入排序總結:
- 插入排序的算法時間平均複雜度爲O(n²)。
- 插入排序空間複雜度爲 O(1)。
- 插入排序爲穩定排序。
- 插入排序對於近乎有序的數組來說效率更高,插入排序可用來優化高級排序算法。