選擇排序思路
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。
具體實現方法
①初始狀态:無序區為R[0..n-1](共n個元素),有序區為空。
②第1趟排序
設置一個變量i,讓i從0至n-2循環的同時,在對比數組中元素i跟元素i+1的大小,如果R[i+1]比R[i]小,則用一個變量k來記住他的位置(即k=i+1)。等到循環結束的時候,我們應該找到了R中最小的那個數的位置了。然後進行判斷,如果這個最小元素的不是R的第一個元素,就讓第一個元素跟他交換一下值,使R[0..0]和R[1..n-1]分别變為記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。
③第i趟排序
第i趟排序開始時,當前有序區和無序區分别為R[0..i-1]和R[i..n-1]。該趟排序從當前無序區中選出關鍵字最小的記錄 R[k],将它與無序區的第1個記錄R交換,使R[0..i]和R分别變為記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。
圖1為一個具體例子:(通過尋找最小值的選擇排序)
算法性能
時間複雜度
選擇排序的交換操作介于 0 和 (n - 1)次之間。選擇排序的比較操作為 n (n - 1) / 2 次之間。選擇排序的賦值操作介于 0 和 3 (n - 1) 次之間。比較次數O(n^2),比較次數與關鍵字的初始狀态無關,總的比較次數N=(n-1)+(n-2)+...+1=n*(n-1)/2。交換次數O(n),最好情況是,已經有序,交換0次;最壞情況交換n-1次,逆序交換n/2次。交換次數比冒泡排序少多了,由于交換所需CPU時間比比較所需的CPU時間多,n值較小時,選擇排序比冒泡排序快。
穩定性
選擇排序是給每個位置選擇當前元素最小的,比如給第一個位置選擇最小的,在剩餘元素裡面給第二個元素選擇第二小的,依次類推,直到第n-1個元素,第n個元素不用選擇了,因為隻剩下它一個最大的元素了。那麼,在一趟選擇,如果一個元素比當前元素小,而該小的元素又出現在一個和當前元素相等的元素後面,那麼交換後穩定性就被破壞了。舉個例子,序列5 8 5 2 9,我們知道第一遍選擇第1個元素5會和2交換,那麼原序列中兩個5的相對前後順序就被破壞了,所以選擇排序是一個不穩定的排序算法。
樹形
輸入輸出
輸入輸出與基本選擇排序相同。
思想
利用滿二叉樹的性質,将輸入的數據存放到滿二叉樹的葉節點,通過比較樹中剩餘可用節點(從底層的葉節點開始)的大小,每次選擇最小的數值(比較複制到二叉樹的頂端),并且把最小數值賦給排序數組的前端,把最小數值原來葉節點的位置設置為不可用;依次循環直至最後一個可用葉節點。
堆
堆分為大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大于其父節點的值,即A[PARENT[i]] >= A[i]。在數組的非降序排序中,需要使用的就是大根堆,因為根據大根堆的要求可知,最大的值一定在堆頂。
既然是堆排序,自然需要先建立一個堆,而建堆的核心内容是調整堆,使二叉樹滿足堆的定義(每個節點的值都不大于其父節點的值)。接下來就是調堆和循環調堆,具體參見堆排序。
思想含義
n個記錄的文件的直接選擇排序可經過n-1趟直接選擇排序得到有序結果:
①初始狀态:無序區為R[1..n],有序區為空。
②第1趟排序
在無序區R[1..n]中選出關鍵字最小的記錄R[k],将它與無序區的第1個記錄R交換,使R[1..1]和R[2..n]分别變為記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。
……
③第i趟排序
第i趟排序開始時,當前有序區和無序區分别為R[1..i-1]和R(i..n)。該趟排序從當前無序區中選出關鍵字最小的記錄 R[k],将它與無序區的第1個記錄R交換,使R[1..i]和R分别變為記錄個數增加1個的新有序區和記錄個數減少1個的新無序區。
常見的選擇排序細分為簡單選擇排序、樹形選擇排序(錦标賽排序)、堆排序。上述算法僅是簡單選擇排序的步驟。
通俗的解釋:
對比數組中前一個元素跟後一個元素的大小,如果後面的元素比前面的元素小則用一個變量k來記住他的位置,接着第二次比較,前面“後一個元素”現變成了“前一個元素”,繼續跟他的“後一個元素”進行比較如果後面的元素比他要小則用變量k記住它在數組中的位置(下标),等到循環結束的時候,我們應該找到了最小的那個數的下标了,然後進行判斷,如果這個元素的下标不是第一個元素的下标,就讓第一個元素跟他交換一下值,這樣就找到整個數組中最小的數了。然後找到數組中第二小的數,讓他跟數組中第二個元素交換一下值,以此類推。
排序特點複雜
選擇排序的交換操作介于 0 和 (n - 1) 次之間。選擇排序的比較操作為 n (n - 1) / 2 次之間。選擇排序的賦值操作介于 0 和 3 (n - 1) 次之間。
比較次數O(n^2),比較次數與關鍵字的初始狀态無關,總的比較次數N=(n-1)+(n-2)+...+1=n*(n-1)/2。交換次數O(n),最好情況是,已經有序,交換0次;最壞情況是,逆序,交換n-1次。交換次數比冒泡排序少多了,由于交換所需CPU時間比比較所需的CPU時間多,n值較小時,選擇排序比冒泡排序快。
其他排序算法的複雜度如右圖所示。
穩定
選擇排序是給每個位置選擇當前元素最小的,比如給第一個位置選擇最小的,在剩餘元素裡面給第二個元素選擇第二小的,依次類推,直到第n-1個元素,第n個元素不用選擇了,因為隻剩下它一個最大的元素了。那麼,在一趟選擇,如果一個元素比當前元素小,而該小的元素又出現在一個和當前元素相等的元素後面,那麼交換後穩定性就被破壞了。比較拗口,舉個例子,序列5 8 5 2 9,我們知道第一遍選擇第1個元素5會和2交換,那麼原序列中2個5的相對前後順序就被破壞了,所以選擇排序不是一個穩定的排序算法。
排序實例
初始關鍵字 [49 38 65 97 76 13 27 49]
第一趟排序後 13 [38 65 97 76 49 27 49]
第二趟排序後 13 27 [65 97 76 49 38 49]
第三趟排序後 13 27 38 [97 76 49 65 49]
第四趟排序後 13 27 38 49 [76 97 65 49 ]
第五趟排序後 13 27 38 49 49 [97 65 76]
第六趟排序後 13 27 38 49 49 65 [97 76]
第七趟排序後 13 27 38 49 49 65 76
最後排序結果 13 27 38 49 49 65 76 97
#include #include void swap(int *a, int *b){ int temp; temp = *a; *a = *b; *b = temp;}void select_sort(int A[], int n){ register int i, j, min, m; for(i=0; ij++) { if(A[min] > A[j]) { min = j; } } if(min != i) { swap(&A[min], &A[i]); printf("第%d趟排序結果為:n", i+1); for(m=0; m 0) { printf(" "); } printf("%d", A[m]); } printf("n"); } }}int main(void){ int n; while(scanf("%d", &n) != EOF) { int i; int *A = (int *)malloc(sizeof(int)*n); for(i=0; i 0) { printf(" "); } printf("%d", A[i]); } printf("n"); } return 0;} 語言C#
C#語言選擇排序算法:
static void 選擇排序(int [] group) { int temp; int pos = 0; for (int i = 0; i < group.Length-1; i++) { pos = i; for (int j = i + 1; j < group.Length; j++) { if (group[j] < group[pos]) { pos = j; } } //第i個數與最小的數group[pos]交換 temp = group[i]; group[i] = group[pos]; group[pos] = temp; } }C
C語言:void select_sort(int *a, int n){ register int i, j, min, t; for( i =0; i < n -1; i ++) { min = i; //查找最小值 for( j = i +1; j < n; j ++) if( a[min] > a[j]) min = j; //交換 if(min != i) { t = a[min]; a[min] = a[i]; a[i] = t; } } }
C++選擇排序算法:
#include#include#includeusing namespace std;const int N=10; int main(){ int a[N], i, j, temp, b; srand(time(NULL)); for(i=0;icout<<
選擇排序法的第一層循環從起始元素開始選到倒數第二個元素,主要是在每次進入的第二層循環之前,将外層循環的下标賦值給臨時變量,接下來的第二層循環中,如果發現有比這個最小位置處的元素更小的元素,則将那個更小的元素的下标賦給臨時變量,最後,在二層循環退出後,如果臨時變量改變,則說明,有比當前外層循環位置更小的元素,需要将這兩個元素交換.
Java
JAVA選擇排序算法:
public static void selectSort(int a[]){ int minIndex = 0; int temp = 0; if((a==null)||(a.length==0)) return; for(int i=0; i
PASCAL選擇排序算法:
procedure ssort(a:array of integer);{a為元素數組}var i,j,k,temp:integer;beginfor i:=n downto 2 do{共n-1輪選擇}begink:=1;for j:=1 to i doif a[j]>a[k] then k:=j;{第i輪,記錄前i個數中最大的}begin {複合語句需要加入begin和end}temp:=a[k];{把最大的與倒數第i個交換}a[k]:=a[i];a[i]:=temp;end;end;end.
public class Test
{
public static int[] a = { 8,32,1,9,5,7,12,0,4,3 }; //預設整數數組
public static void main(String args[])
{
int index = a.length;//數組長度
System.out.print("排序前: ");
for (int i = 0; i < index; i++)//遍曆數組
System.out.printf("%3s",a[i]);
System.out.println("");
//選擇排序
SelectSort(index);
System.out.print("排序後: ");
for (int i = 0; i < index; i++)
System.out.printf("%3s",a[i]);
System.out.println("");
}
public static void SelectSort(int index)
{
for (int i = 0; i < index - 1; i++)
{
for (int j = i+1; j < index; j++)
{
if(a[i]>a[j])//i、j分别代表前、後角标,假如數組i角标所在的值大于j的值,就把i的值賦值給臨存變量temp,兩者再進行位置置換。
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
System.out.print("排序中: ");
for (int k = 0; k < index; k++)
System.out.printf("%3s",a[k]);
System.out.println("");
}
}
}
Perl
PERL選擇排序算法:
#!/usr/bin/perlsub select_sort{my (*array)=@_;$length=@array;for($i=0;$i<$length-1;$i++){$min=$i;for($j=$i+1;$j<$length;$j++){if($array[$j]<$array[$min]){$min=$j;}if($min!=$i){$temp=$array[$i];$array[$i]=$array[$min];$array[$min]=$temp;}}return @array;}php
PHP選擇排序算法:
'.$array[$min].'-->'; for ($j=$i+1;$j<$count;$j++) { //由小到大排列 if ($array[$min]>$array[$j]) { //表明當前最小的還比當前的元素大 $min = $j; //賦值新的最小的 } } echo $array[$min].'coco
'; /* swap $array[$i] and $array[$min] 即将當前内循環的最小元素放在$i位置上*/ if($min!=$i) { $temp = $array[$min]; $array[$min] = $array[$i]; $array[$i] = $temp; } } return $array;}$old_array = array(3,4,1,6,5,2);$new_array = selection_sort($old_array);print_r($new_array);?>vb
vb選擇排序算法:
Private Sub xzPaiXu(a() As Double, sheng As Boolean) 'a為需要排序的數組,sheng為True則為升序排列,為False,則為降序排列。 Dim i As Integer, j As Integer Dim temp As Double Dim m As Integer For i = LBound(a) To UBound(a) - 1 '進行數組大小-1輪比較 m = i '在第i輪比較時,假定第 'i個元素為最值元素 For j = i + 1 To UBound(a) '在剩下的元素中找出最 '值元素的下标并記錄在m中 If sheng Then '若為升序,則m記錄最小元素 '下标,否則記錄最大元素下标 If a(j) < a(m) Then m = j Else If a(j) > a(m) Then m = j End If Next j '将最值元素與第i個元素交換 temp = a(i) a(i) = a(m) a(m) = temp Next iEnd Sub
算法
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。n再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。n重複第二步,直到所有元素均排序完畢。



















