選擇排序

選擇排序

數學術語
選擇排序(Selection sort)是一種不穩定的排序方法,每一趟從待排序的數據元素中選出最小(或最大)的一個元素,順序放在已排好序的數列的最後,直到全部待排序的數據元素排完。其主要應用于計算機和數學領域。它的主要優點與數據移動有關。如果某個元素位于正确的最終位置上,則它不會被移動。選擇排序每次交換一對元素,它們當中至少有一個将被移到其最終位置上,因此對n個元素的表進行排序總共進行至多n-1次交換。在所有的完全依靠交換去移動元素的排序方法中,選擇排序屬于非常好的一種。
    中文名:選擇排序 外文名:Selection sort 性質:不穩定的排序方法 代表:PERL選擇排序算法 适用範圍:數據元素 方法:通過比較 應用領域:計算機,數學

選擇排序思路

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

具體實現方法

①初始狀态:無序區為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重複第二步,直到所有元素均排序完畢

相關詞條

相關搜索

其它詞條