选择排序是所有排序算法中非常简单又非常基础的算法,逻辑简单、容易实现,好多复杂算法都是由这些简单的算法演变而来。所以想要学好算法,必须先从这些简单算法学起,循序渐进,为后面学习复杂算法打下基础。本篇主要从“基本原理、排序流程、核心代码、算法性能、稳定性、参考代码”等几个方面介绍这一算法。
基本原理:从待排序列中找到最小(或最大)的元素,和序列的第一个元素交换位置;然后从剩余的元素中找到最小(或最大)的元素,和序列的第二个元素交换位置……以此类推,直到整个序列排序完毕。
排序流程:以下以序列:5 3 0 4 1 9 7 2 6 8为例,红色元素表示当前序列最小元素,加粗元素表示每一趟参与比较的元素,未加粗元素表示已经排好的元素(未参与比较)。
趟数 | 排序前 | 排序后 | 说明 |
1 | 5 3 0 4 1 9 7 2 6 8 | 0 3 5 4 1 9 7 2 6 8 | 0元素最小,与第一个元素5交换位置 |
2 | 0 3 5 4 1 9 7 2 6 8 | 0 1 5 4 3 9 7 2 6 8 | 1元素最小,与第二个元素3交换位置 |
3 | 0 1 5 4 3 9 7 2 6 8 | 0 1 2 4 3 9 7 5 6 8 | 2元素最小,与第三个元素5交换位置 |
4 | 0 1 2 4 3 9 7 5 6 8 | 0 1 2 3 4 9 7 5 6 8 | 3元素最小,与第四个元素4交换位置 |
5 | 0 1 2 3 4 9 7 5 6 8 | 0 1 2 3 4 9 7 5 6 8 | 4元素最小,与第五个元素4交换位置 |
6 | 0 1 2 3 4 9 7 5 6 8 | 0 1 2 3 4 5 7 9 6 8 | 5元素最小,与第六个元素9交换位置 |
7 | 0 1 2 3 4 5 7 9 6 8 | 0 1 2 3 4 5 6 9 7 8 | 6元素最小,与第七个元素7交换位置 |
8 | 0 1 2 3 4 5 6 9 7 8 | 0 1 2 3 4 5 6 7 9 8 | 7元素最小,与第八个元素9交换位置 |
9 | 0 1 2 3 4 5 6 7 9 8 | 0 1 2 3 4 5 6 7 8 9 | 8元素最小,与第九个元素9交换位置 |
10 | 0 1 2 3 4 5 6 7 8 9 | 0 1 2 3 4 5 6 7 8 9 | 9元素最小,与第十个元素9交换位置 |
最终排序结果为:0 1 2 3 4 5 6 7 8 9。
核心代码:以Java为例。
public static void sort(int[] a) { int len = a.length; //数组长度 for (int i = 0; i < len; i++) { //第一个for循环指定排序趟数 int min = i; //最小元素位置 for (int j = i+1; j < len; j++) { //第二个for循环找出序列最小元素 if (a[j]<a[min]) min = j; //如果j位置元素小于当前最小元素,则将j位置赋值给min } int cha = a[i]; //把最小位置元素与i位置元素交换 a[i] = a[min]; a[min] = cha; } }
算法性能:算法性能的好坏直接决定算法执行效率的高低,衡量算法性能有一些常用的指标,比如时间复杂度、空间复杂度,同时不同的编码、不同的机器硬件等因素也会影响算法执行效率。对于长度为N的序列,选择排序每一趟选择最小元素,都要比较未排序元素的大小,所以比较总次数为:(N-1)+(N-2)+……+2+1=N(N-1)/2;每次选出最小元素进行交换都能排定一个元素,所以交换总次数为:N。综上,时间复杂度为O(N²),空间复杂度为O(1)。
稳定性:假如序列中存在两个或多个相同的元素,排序之后他们的相对次序不发生改变(如某序列存在Ni=Nj,排序前Ni在Nj前面;排序后Ni依然在Nj前面),则排序算法是稳定的,否则是不稳定的。选择排序是不稳定的排序算法,比如序列[2,2,1],第一趟排序后变成[1,2,2],第一个2(红色)与1交换位置,两个2的相对位置发生改变,所以是不稳定的。
总的来说选择排序算法是一种非常容易理解和实现的简单排序算法,它的元素移动次数是最少的,只进行N次交换,交换次数和序列大小是线性关系,其余算法大部分增长数量级都是线性对数或是平方级别的。当然,选择排序算法每一趟只会机械的遍历序列来找出最小元素,如果序列已经有序或所有元素都相等,显然这种遍历是多余的,这是选择排序一大缺点。
参考代码:以Java为例。
import java.util.Random; /* * 选择排序 */ public class SelectionSort { public static void sort(int[] a) { int len = a.length; //数组长度 for (int i = 0; i < len; i++) { //第一个for循环指定排序趟数 int min = i; //最小元素位置 for (int j = i+1; j < len; j++) { //第二个for循环找出序列最小元素 if (a[j]<a[min]) min = j; //如果j位置元素小于当前最小元素,则将j位置赋值给min } int cha = a[i]; //把最小位置元素与i位置元素交换 a[i] = a[min]; a[min] = cha; } } public static void main(String[] args) { Random random = new Random(); int[] arg1 = new int[20]; for(int n=0;n<20;n++){ //从[0-100]中生成20个随机数 arg1[n] = random.nextInt(100); } System.out.println("排序前:"); for (int i = 0; i < arg1.length; i++) { System.out.print(arg1[i]+" "); } System.out.println("\n排序后:"); long startTime = System.currentTimeMillis(); //获取开始时间 sort(arg1); long endTime = System.currentTimeMillis(); //获取结束时间 for (int i = 0; i < arg1.length; i++) { System.out.print(arg1[i]+" "); } System.out.println("\n排序时长:"+(endTime-startTime)+"ms"); } }
运行结果:
排序前: 19 31 52 70 44 6 59 54 29 80 95 79 37 48 99 63 77 38 67 33 排序后: 6 19 29 31 33 37 38 44 48 52 54 59 63 67 70 77 79 80 95 99 排序时长:0ms
转载请注明出处 http://www.cnblogs.com/Y-oung/p/7739536.html
工作、学习、交流或有任何疑问,请联系邮箱:yy1340128046@163.com