思路:
選擇排序法是一種非常直觀的算法,它會在計算每個計算步驟中選出一個最小值,進而完成排序。
模板:
selectionSort(A ,N) //包含N個元素的0起點數組A for i 從 0到 N-1 min=i for j 從 i到N-1 if A[j] < A[min] min = j A[ i ]與A[ min ]交換 _________________________________________ void selectionSort(A[] ,N) { int i,j,t,min; for(i=0;i < N-1;i++) { min = i; for(j = i;j < N;j++) { if(A[j] < A[min]) min =j; } if( i != min) { t = A[ i ]; A[ i ] = A[min]; A[min] = t; } } }
C++模板:
#include<bits/stdc++.h> using namespace std; void selectionSort(int a[],int n) { int i,j,t,min; for(i=0;i<n-1;i++) { min=i; for(j=i+1;j<n;j++) //個人喜歡用j=i+1,而不是j=i { if(a[j]<a[min]) min=j; } if(i!=min) { t=a[i]; a[i]=a[min]; a[min]=t; } } } int main() { int a[100],n,i; cin>>n; for(i=0;i<n;i++) cin>>a[i]; selectionSort(a,n); for(i=0;i<n;i++) { if(i) cout<<" "; cout<<a[i]; } cout<<endl; return 0; }
時間復雜度:
由於選擇排序法會直接交換兩個不相鄰的元素,所以屬於不穩定的排序算法。
然后再來看看選擇排序法的復雜度。假設數據總數為N,那么無論在何種情況下,選擇排序法都需要進行(N - 1) + (N - 2) + ··· + 1 = (N2 - N)/2次比較運算,用於搜索未排序部分的最小值。因此該算法的復雜度與N2基本成正比,即復雜度數量級為O(N2)。
現在,讓我們回過頭來看看這三種排序算法(插入、冒泡、選擇),比較一下它們的特征。冒泡排序法與選擇排序法相比,一個從局部入手減少逆序元素,一個放眼大局逐個選擇最小值,二者思路大不相同。但是,它們又都有着“通過 i 次外層循環,從數據中順次求出 i 個最小值”的相同特征。相對的,插入排序法是通過 i 次外層循環,直接將原數組的 i 個元素重新排序。另外,不含flag的簡單冒泡排序法和選擇排序法不依賴數據,即比較運算次數(算法復雜度)不受輸入數據的影響,而插入算法在執行時卻依賴數據,處理某些數據是具有很高的效率。
例題:
請編寫一個程序,讀取數列 A,利用選擇排序法將其按升序排列並輸出。程序中需包含上述偽代碼所表示的算法。
另外,請輸出程序實際運行過程中執行交換操作(即偽代碼第 7 行中 i 與 min不相等的情況)的次數。
輸入:在第 1 行輸入定義數組長度的整數N。在第 2 行輸入 N個整數,以空格區分。
輸出:輸出總計 2 行。請在第 1 行輸出排序后的數列。數列相鄰元素用 1 個空格隔開。第 2 行輸出交換次數。
限制:1≤ N ≤ 100
0≤ A的元素 ≤ 100
輸入示例
6 5 6 4 2 1 3
輸出示例
1 2 3 4 5 6 4
C++代碼:
#include<bits/stdc++.h> using namespace std; int selectionSort(int a[],int n) { int i,j,t,sum=0,min; for(i=0;i<n-1;i++) { min=i; for(j=i;j<n;j++) { if(a[j]<a[min]) min=j; } if(i!=min) { t=a[i]; a[i]=a[min]; a[min]=t; sum++; } } return sum; } int main() { int a[100],n,i,sum; cin>>n; for(i=0;i<n;i++) cin>>a[i]; sum=selectionSort(a,n); for(i=0;i<n;i++) { if(i) cout<<" "; cout<<a[i]; } cout<<endl; cout<<sum<<endl; return 0; }
例題網址:
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_2_B
