1. 程式人生 > >從零開始學演算法(三)插入排序

從零開始學演算法(三)插入排序

從零開始學演算法(三)插入排序

插入排序

程式碼是Javascript語言寫的(幾乎是虛擬碼)

演算法介紹

插入排序(Insertion Sort)引用左老師的一句話理解:“就像是手裡抓好了一副排好順序的牌,新抓一張以後,從後往前劃,一張張比較,最後在合適的位置把它插進去

演算法原理

劃分“手牌區”以及將待插入元素與“手牌區”裡排好序的元素進行大小比較,依此向前逐個比較,待插入的元素小於比較的元素,則交換位置,完成插入後“手牌區”向後擴一,再將“手牌區”後的元素依此進行上述操作,以此類推

演算法簡單記憶說明

5,3,4,0,6,2
0,1,2,3,4,5 (位置)
剛開始我們認為0到0是排好序的,即數字5為我們的手牌

第一次比較插入
5,3,4,0,6,2
0,1,2,3,4,5
0位置上的數不動,看1位置上的數與0位置上的數作比較,如果小,就交換位置
3<5交換位置
3,5,4,0,6,2
0,1,2,3,4,5
隨後我們的手牌區變成了3,5兩張牌

第二次比較插入
3,5,4,0,6,2
0,1,2,3,4,5
0和1位置上的數不動,看2位置上的數與手牌區裡的牌依此比較,如果小就交換位置
4<5交換位置
3,4,5,0,6,2
0,1,2,3,4,5
4>3不交換
隨後手牌區變成了3,4,5三張牌

第三次比較插入
3,4,5,0,6,2
0,1,2,3,4,5
手牌區的數不動,看3位置上的數與手牌區裡的牌依此比較,如果小就交換位置
0<5交換位置
3,4,0,5,6,2
0,1,2,3,4,5
0<4交換位置
3,0,4,5,6,2
0,1,2,3,4,5
0<3交換位置
0,3,4,5,6,2
0,1,2,3,4,5

第四次比較插入

以此類推

最終排好序:0,2,3,4,5,6

演算法複雜度和穩定性

插入排序的時間複雜度是與資料狀況有關的

  • 資料順序排好為O(N)
  • 資料逆序排好為O(N2)

插入排序是穩定排序演算法

演算法穩定性的定義: 假設在數列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;並且排序之後,a[i]仍然在a[j]前面。則這個排序演算法是穩定的。

插入排序選擇選第一個元素為有序的,後面的元素和手牌區裡的元素作比較,比手牌區裡元素大的就放在它後面,比它小就和它交換位置,和它相等,就放在它後面。所以插入排序是穩定的

程式碼實現

var Insertionarr=[5,3,4,0,6,2];
function InsertionSort(arr){
	if(arr==null||arr.length<2){return;}
	for(var i=1;i<arr.length;i++){
		for(var j=i-1;j>=0&&arr[j]>arr[j+1];j--){
			swap(arr,j,j+1);
		}
	}
	return arr;
}
function swap(arr,i,j){
	arr[i]=arr[i]^arr[j];
	arr[j]=arr[i]^arr[j];
	arr[i]=arr[i]^arr[j];
}

InsertionSort(Insertionarr);
console.log(Insertionarr);

輸出結果:0,2,3,4,5,6

程式碼解釋:
第一個for迴圈i相當於要插的牌,因為預設0位置的已經排好,所以i從1開始
第二個for迴圈,j>=0表示不越界,如果arr[j]>arr[j+1],則交換它們,之後j–則相當於開始往前走往前繼續比較,直到不滿足for迴圈條件

假設一個要插入的數字a它的位置為i,j=i-1

a
i-1 i
j j+1

很容易看出j-1之後,j+1=i-1,相當於往前移動比較