选择排序的基本思想:每次从待排序的记录中选出关键字最小(或最大的)记录,顺序存放已经排序的记录序列的后面(或前面),直到全部排完。
同插入排序一样,分为有序段和无序段,不同的的是选择排序是从没有排好序段中找出最小(或最大)的元素添加在有序序列段后后面,这样子有序序列段不断边长,直至所有的序列均排好序。
实例分析:(红色表示已经有序段,黑色表示无序段,绿色表示刚被替换的元素)
初始状态: 70 30 40 10 80 20 90 100 75 60 45 共11个元素
第一次: 10 30 40 70 80 20 90 100 75 60 45 刚开始所有的序列均认为是无序的,从中找出最小值 10 并与a[0]交换
第二次: 10 20 40 70 80 30 90 100 75 60 45 从剩下的无序段中找出最小值 20 并与a[1]交换
第三次: 10 20 30 70 80 40 90 100 75 60 45 从剩下的无序段中找出最小值 30 并与a[2]交换
第四次: 10 20 30 40 80 70 90 100 75 60 45 从剩下的无序段中找出最小值 40 并与a[3]交换
第五次: 10 20 30 40 45 70 90 100 75 60 80 从剩下的无序段中找出最小值 45 并与a[4]交换
第六次: 10 20 30 40 45 60 90 100 75 70 80 从剩下的无序段中找出最小值 60 并与a[5]交换
第七次: 10 20 30 40 45 60 70 100 75 90 80 从剩下的无序段中找出最小值 70 并与a[6]交换
第八次: 10 20 30 40 45 60 70 75 100 90 80 从剩下的无序段中找出最小值 75并与a[7]交换
第九次: 10 20 30 40 45 60 70 75 80 90 100 从剩下的无序段中找出最小值 80 并与a[8]交换
第十次: 10 20 30 40 45 60 70 75 80 90 100 从剩下的无序段中找出最小值 90 ,此时不用交换 ,此时程序已经排好序了
参考代码:
#include <stdio.h> #define MAX_NUM 80 void selectsort(int* a, int n) { for (int i = 0; i < n-1; i++) { int k = i; for(int j = i+1; j < n; j++) { if(a[k] > a[j]) { k = j; } } if( k != i) { int t = a[i]; a[i]=a[k]; a[k] = t; } for(int i = 0; i < n;i++) { printf("%d ",a[i]); } printf("\n"); } } int main(int argc, char* argv[]) { int a[MAX_NUM]; int n; printf("Input total numbers: "); scanf("%d",&n); if( n > MAX_NUM ) n = MAX_NUM; for(int i = 0; i < n;i++) { scanf("%d",&a[i]); } printf("排序步骤:\n"); selectsort(a,n); return 0; }
案例结果截图:
选择排序算法效率与稳定性分析
在选择排序中,第一次排序要进行n-1次比较,第二次排序要进行n-2比较,第n-1次排序比较需要进行一次比较,所以总的比较次数为n(n-1)/2。
在一次排序过程时,记录的移动次数最好是0次,最坏为3次,因此,总的移动次数最好为0次,最坏为3次,虽然整个排序古城中移动次数不多,但是总的比较次数很多,因此选择排序算法的时间复杂度为O(n2)。
选择排序算法只需要一个辅助空间用于记录交换记录以及另一个用于记录,对于存储空间没有过高的要求。在排序过程中,每次比较和值交换都只在两个元素之间,故序列中关键字相同的元素其位置不会发生改变,所以,选择排序算法是一种稳定的排序方法。
注:主要参考彭军、向毅主编的 《数据结构与算法》