作者前言

大家好,我是阿濠,今篇内容跟大家分享的是排序算法之选择排序,很高兴分享到segmentfault与大家一起学习交流,初次见面请大家多多关照,一起学习进步.

一、选择排序的介绍

基本介绍

选择式排序也属于内部排序法,是从欲排序的数据中,按指定的规则选出某一元素,再依规定交换位置达到排序的目的

排序思想

1.第1次从arr[0] ~ arr[n-1]中选取最小值,与arr[0]交换
2.第2次从arr[1] ~ aarr[n-1]中选取最小值,与arr[1J交换
3.第3次从arr[2] ~ arr[n-1]中选取最小值,与arr[2]交换
4.第i次从arr[i-1] ~ arr[n-1]中选取最小值,与arr[i-1]交换
5.第n-1次从arr[n-2] ~ arr[n-1]中选取最小值,与arr[n-2] 交换

总共通过n-1次,得到一个按排序码从小到大排列的有序序列。

二、通过应用示例认识选择排序

由一群牛,颜值分别是: 100,34,119,1 使用选择排序法将其排成一个从小到大的有序数列。

图片.png

步骤思路:
1.需要进行数组大小-1的循环
2.每次循环定义当前数是最小数,与后面数比较若更小确定最小数并得到下标进行交换

//使用逐步推导的方式来,讲解选择排序
//第1轮
//原始的数组:101, 34, 119, 1
//第一轮排序: 1, 34, 119,101
//算法先简单-->再复杂
//就是可以把一个复杂的算法,拆分成简单的问题-》逐步解决
int minIndex = 0;//最小值下标
int min = arr[0];//最小值为当前第一个数
for(int j = 0 + 1; j < arr.length; j++){
    //若最小值比其他还大,则说明不是最小值
    if (min > arr[j]) {
        min = arr[j];
        minIndex = j;
    }
}
if(minIndex!=0){
    //将当前最小值与之前最小值进行交换
    arr[minIndex] = arr[0];
    arr[0] = min;
}


System.out.println("第一轮交换后");
System.out.println(Arrays.toString(arr));

运行结果如下:
排序前:[101, 34, 119, 1]
第一轮交换后:[1, 34, 119, 101]
//第二轮
minIndex = 1;//最小值下标
min = arr[1];//最小值为当前第一个数
for(int j = 1 + 1; j < arr.length; j++){
    //若最小值比其他还大,则说明不是最小值
    if (min > arr[j]) {
        min = arr[j];
        minIndex = j;
    }
}
if(minIndex!=1){
    //将当前最小值与之前最小值进行交换
    arr[minIndex] = arr[1];
    arr[1] = min;
}
System.out.println("第二轮交换后");
System.out.println(Arrays.toString(arr));

运行结果如下:
第一轮交换后:[1, 34, 119, 101]
第二轮交换后:[1, 34, 119, 101]
//第三轮
minIndex = 2;//最小值下标
min = arr[2];//最小值为当前第一个数
for(int j = 2 + 1; j < arr.length; j++){
    //若最小值比其他还大,则说明不是最小值
    if (min > arr[j]) {
        min = arr[j];
        minIndex = j;
    }
}
if(minIndex!=2){
    //将当前最小值与之前最小值进行交换
    arr[minIndex] = arr[2];
    arr[2] = min;
}
System.out.println("第三轮交换后");
System.out.println(Arrays.toString(arr));

运行结果如下:
第一轮交换后:[1,34,119,101]
第二轮交换后:[1,34,119,101]
第三轮交换后:[1,34,101,119]

规律已经出来了,最小值、判断交换相似,改变的是每次最小值的下标,即进行如下代码抽整:

//时间复杂度是O(n^2)
for (int i=0 ;i<arr.length;i++){

    int minIndex = i;//最小值下标
    int min = arr[i];//最小值为当前第一个数

    for(int j = i + 1; j < arr.length; j++){

        //若最小值比其他还大,则说明不是最小值
        if (min > arr[j]) {
            min = arr[j];
            minIndex = j;
        }

    }
    if(minIndex != i){
        //将当前最小值与之前最小值进行交换
        arr[minIndex] = arr[i];
        arr[i] = min;
    }
    System.out.println("第"+(i+1)+"轮交换后");
    System.out.println(Arrays.toString(arr));
}

//运行结果如下:
//排序前:[101, 34, 119, 1]

排序后
第1轮交换后:[1, 34, 119, 101]
第2轮交换后:[1, 34, 119, 101]
第3轮交换后:[1, 34, 101, 119]
第4轮交换后:[1, 34, 101, 119]

三、复杂度分析

选择排序的交换操作介于0和(n-1)次之间

选择排序的比较操作为n(n-1)/2次之间

选择排序的赋值操作介于0和3(n-1)次之间

比较次数O(n^2),比较次数与关键字初始状态无关总的比较次数N=(n-1)+(n-2)+...+1=n*(n-1)/2

交换次数O(n),最好情况是,已经有序交换0次;最坏情况是,逆序交换n-1次

交换次数比冒泡排序少多了,由于交换所需CPU时间比比较所需的CPU时间多,n值较小时,选择排序比冒泡排序快


28640
116 声望25 粉丝

心有多大,舞台就有多大