排序算法之选择排序

        选择排序是所有排序算法中非常简单又非常基础的算法,逻辑简单、容易实现,好多复杂算法都是由这些简单的算法演变而来。所以想要学好算法,必须先从这些简单算法学起,循序渐进,为后面学习复杂算法打下基础。本篇主要从“基本原理、排序流程、核心代码、算法性能、稳定性、参考代码”等几个方面介绍这一算法。

        基本原理:从待排序列中找到最小(或最大)的元素,和序列的第一个元素交换位置;然后从剩余的元素中找到最小(或最大)的元素,和序列的第二个元素交换位置……以此类推,直到整个序列排序完毕。

        排序流程:以下以序列: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("
排序后:");
        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("
排序时长:"+(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

原文地址:https://www.cnblogs.com/Y-oung/p/7739536.html