1. 程式人生 > >從零開始學演算法(二)選擇排序

從零開始學演算法(二)選擇排序

從零開始學演算法(二)選擇排序

選擇排序

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

演算法介紹

選擇排序(Selection Sort),是一種簡單直觀的排序演算法

通過每一次從待排序的資料元素中選出最小(或最大)的一個元素,存放在序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到全部待排序的資料元素排完。

演算法原理

記憶方法
相當於反向的氣泡排序,從0到n-1這些數裡找到一個最小的放在0位置,再從1到n-1這些數裡找到一個最小的放在1位置,再從2到n-1這些數中找到一個最小的放在2位置,以此類推。

官方解釋
對比數列中前一個元素跟後一個元素的大小,如果後面的元素比前面的元素小則用一個變數k來記住他的位置,接著第二次比較,前面“後一個元素”現變成了“前一個元素”,繼續跟他的“後一個元素”進行比較如果後面的元素比他要小則用變數k記住它在陣列中的位置(下標),等到迴圈結束的時候,我們應該找到了最小的那個數的下標了,然後進行判斷,如果這個元素的下標不是第一個元素的下標,就讓第一個元素跟他交換一下值,這樣就找到整個陣列中最小的數了。然後找到陣列中第二小的數,讓他跟陣列中第二個元素交換一下值,以此類推。

可能有點抽象,詳細的舉個例子來說明

演算法簡單記憶說明

2,7,3,6,5,1
0,1,2,3,4,5 (位置)
剛開始假設第一個數字是最小的,即n=0的數字,我們用一個最小標記minIndex來標記它,即minIndex=0
隨後我們開始將1-5位置的5個數開始與帶有minIndex標記的數作比較,如果數字小於標記的數字,那麼將標記移到這個小的數字上直到5個數全部比較完,將標記的數字和頭數字進行交換,頭數字每一輪向後移一個,以此類推

第一遍:(0~n-1)
2,7,3,6,5,1
0,1,2,3,4,5
7>2標記不移動
3>2標記不移動
6>2標記不移動
5>2標記不移動
1<2minIndex標記從0位置移到5位置
2,7,3,6,5,1
0,1,2,3,4,5


隨後將0位置的數與minIndex上的數交換,這樣得到最小的值放在首位值
1,7,3,6,5,2
0,1,2,3,4,5

第二遍:(1~n-1)
1,7,3,6,5,2
0,1,2,3,4,5
首位置最小值確定下來,我們將minIndex標記向後移一位,隨後再從minIndex標記的元素後的所有元素和它作比較,重複上面的步驟
1,7,3,6,5,2
0,1,2,3,4,5
3<7minIndex標記移到2位置上
1,7,3,6,5,2
0,1,2,3,4,5
6>3標記不移動
5>3標記不移動
2<3minIndex標記移到5位置上
1,7,3,6,5,2
0,1,2,3,4,5
隨後將1位置上的數與minIndex標記的數交換,找到這一輪比較中的最小值
1,2,3,6,5,7
0,1,2,3,4,5

第三遍:(2~n-1)
1,2,3,6,5,7
0,1,2,3,4,5

以此類推

最終排好序:1,2,3,5,6,7

演算法複雜度和穩定性

選擇排序的時間複雜度是O(N2

選擇最小值的操作內迴圈比較N - 1次,然後是N-2次,N-3次,……,最後一次內迴圈比較1次。這是一個等差數列,時間複雜度為O(N2)。

選擇排序是不穩定排序演算法

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

如何理解?舉個例子:
3,6,(3),1,8
第一遍:1,6,(3),3,8
我們看到2個3的順序已經改變了

程式碼實現

var Selectionarr = [2,7,3,6,5,1];
function SelectionSort(arr){
	if(arr == null || arr.length<2){return;}
	for(var i=0;i<arr.length-1;i++){
	    minIndex = i;
		for(var j=i+1;j<arr.length;j++){
		minIndex = arr[j]<arr[minIndex]?j:minIndex;
		swap(arr,i,minIndex);}
	}
	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];
}

SelectionSort(Selectionarr);
console.log(Selectionarr);

輸出結果:1,2,3,5,6,7