直接选择排序算法 代码示例:
//注:关键字值类型为int,数组的索引是从0开始 // 1. 初始状态无序区为array【0, n - 1】,有序区为空。 // 2. 第1趟排序从array【0, n - 1】中找到下标为k的关键字最小值,把array【k】和 // array【0】交换。现在无序区为array【1, n - 1】, 有序区为array【0, 0】。 // 第2趟排序... // 第3趟排序... // ... // 3. 第i趟排序(1 <= i <= n - 1),从array【i, n - 1】中找到下标为j的关键字最小值,把 // array【j】和array【i - 1】交换,如果i == n - 1,则排序结束,否则继续3步骤。 // 算法分析 //1. 关键字比较次数。 // 无论记录的初始状态,比较次数都是1 + 2 + 3 + 4 + ... + (n - 1) = n * (n -1) / 2; //2. 记录移动次数。 // 最好情况下0次, 正序, 最坏情况下3 * (n - 1)次, 反序。 // 那么直接选择排序的时间复杂度就是:O(n * n)。 //3. 直接选择排序是一个就地排序。辅助空间O(1)。 // 非就地排序一般要求的辅助空间为O(n)。 //4. 直接选择排序不稳定的。 // 反例 // 下标:【1 2 3】 // 关键字值:2 2 1 // 进过直接选择排序第一个2和第二个2相对位置发生了改变。 // #include<iostream> using namespace std; void selectSort(int *a,int left,int right){ for(int i=left;i<right;i++){ int k=i; //在a[i]到a[n-1]之间找到最小排序码的元素 for(int j=i+1;j<=right;j++) if(a[j] < a[k]) k=j;//保存具有当前最小排序码的元素的排序码 if( k != i) swap(a[i],a[k]);//交换 } } void main(){ int a[]={23,45,23,434,34,213,454,3421,45,6}; int ARR_LENGTH = (sizeof(a)/sizeof(a[0])); selectSort(a,0,ARR_LENGTH-1); for(int i=0;i<ARR_LENGTH;i++) cout<<a[i]<<" "; cout<<endl; }
直接排序的排序码比较次数KCN与元素的初始排列无关。第 i 趟选择具有最小排序码的元素所需要的比较次数总是 n - i - 1 次,此处假定整个待排序元素有 n 个元素,因此,总的排序码的比较次数为:
KCN =n ( n - 1) / 2
元素的移动次数与元素序列的初始排列有关。当这组元素的初始状态是按照其排序码从小到大有序的时候,元素的移动此时 RMN= 0 ;最坏情况是每一趟都要进行交换,总的移动次数为 RMN = 3 (n-1)。尽管如此,相比其他的排序算法,待排序元素的有序性对于选择排序的运行时间影响不大。因为从未排序部分选择最小元素的每一步操作过程,没有对下一步要找的最小项的位置给出相关信息。因此,对于已经排序好序列的序列 或者 各元素排序码值完全相同的序列,直接选择排序所花费的时间与对随机排列的元素序列所花时间是基本相同。因此选择排序比较简单 并且执行时间比较固定。而对于它对一类重要的元素序列具有较好的效率,这就是元素规模很大,而排序码却比较小的序列。因为它对于这种序列进行排序,移动所花费的时间比比较操作的时间大的多,而其他算法移动操作的次数都要比选择排序来的多。
另外,直接选择排序是一种不稳定的排序算法。