经典排序算法——选择排序

选择排序的原理

选择排序的原理是首先取第一个数字作为数组中的最小者minValue(以升序排序为例),依次跟后续数字进行比较,如果发现有比minValue更小的数字,记录该数字的下标,并将该数字的值赋给minValue,直到遍历完数组的最后一个数字。然后根据记录的实际最小值的下标,跟第一个数字进行交换。

第一趟比较执行完后就找到了数组中最小者,然后再从下一个数字开始,重复执行前面的步骤,直到倒数第二个数字比较完为止(最后数字无需比较即为最大数字)

 图解选择排序过程

假设要排列的数字为 3 1 4 2 ,当进行第一趟排序时,如下图所示(其中i表示数组的下标)

第一趟排序后,数组中最小的数字1已找到并放置在第0位置。下面看第二趟比较,如下图所示。

第二趟比较从第二个数开始,将minIndex设置为1,并将minValue设置为4。并依次跟后面的数比较,发现3<4,将minIndex和minValue修改为对应值。继续向后比较发现2<3,将minIndex和minValue修改为对应值。第二趟遍历结束,将第1位置的值设置为minIndex对应的值2,并将minIndex值设置为4。第二趟比较结束。继续执行第三趟排序(虽然我们看到现在数组已经有序,但程序不知道)。第三趟比较如下图所示

第三趟比较时,将minIndex设置为2,minValue设置为3。依次向后比较,4>3不改变minIndex和minValue。遍历结束,无需进行交换(通过趟数值与minIndex值是否相等来判断是否需要交换)

代码实现

 1 public static void sort(int array[]){
 2         //第一个for循环表示要进行length-1次选择
 3         for (int i = 0; i < array.length - 1; i++) {
 4             int minIndex = i;
 5             int minValue = array[minIndex];
 6             for (int j= i+1; j<array.length; j++){
 7                 if(minValue > array[j]){
 8                     minIndex = j;
 9                     minValue = array[j];
10                 }
11             }
12             //执行完一轮选择后进行交换(如果最小值下标有改变才进行交换)
13             if(minIndex != i){
14                 array[minIndex] = array[i];
15                 array[i] = minValue;
16             }
17         }
18     }

代码分析

1)第一层for循环确定比较趟数,通过我们的分析,比较n-1趟即可(n为数组长度)

2)第二层for循环用于遍历所选择的最小值后续数字,比较是否有小于所选择的最小值,如果有,则修改minIndex和minValue

3)if提交判断,用于判定minIndex是否被修改过,如果没有修改过,则无需交换(否则自己与自己交换,无意义)

时间复杂度

选择排序有两层for循环,所示时间复杂度为T(n)=O^2

测试执行时间

与上一篇冒泡排序相同,依然生成10万个数字进行排序。代码如下

1 public static void main(String []args){
2         int array[] = new int[100000];
3         for (int i = 0; i < 100000; i++) {
4             array[i] = (int) (Math.random()*1000000);
5         }
6         long begin = System.currentTimeMillis();
7         sort(array);
8         System.out.println("总耗时="+(System.currentTimeMillis()-begin));
9     }

执行结果(单位为毫秒)

 

可以看出,在我的机器上使用选择排序对10万个数字的数组进行排序,大概需要3秒多的时间,比冒泡排序的17秒快了很多。下一篇我将讲解插入排序的过程,耗时会不会更小呢?一起期待!!!

总结

选择排序需要注意两点,一是比较的趟数,有n个数,比较n-1即可。二是每趟比较,都认为当前数为最小(或最大)值,然后依次跟后面数字比较,如果发现有比我们假设的最小值更小,则改变成新的下标和新的最小值继续向后比较,直到遍历完所有数字。如果假设的最小值下标有修改则进行交换。

 

posted @ 2019-10-13 12:03  听风1108  阅读(1789)  评论(0编辑  收藏  举报