思路:
选择排序法是一种非常直观的算法,它会在计算每个计算步骤中选出一个最小值,进而完成排序。
模板:
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