【算法】选择排序

从算法逻辑上看,选择排序是一种简单直观的排序算法,在简单选择排序过程中,所需移动记录的次数比较少。

一、基本思想

选择排序的基本思想:比较 + 交换。

在未排序序列中找到最小(大)元素,存放到未排序序列的起始位置。在所有的完全依靠交换去移动元素的排序方法中,选择排序属于非常好的一种。

红色表示当前最小值,黄色表示已排序序列,绿色表示当前位置。

二、算法描述

  1. 从待排序序列中,找到关键字最小的元素;
  2. 如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换;
  3. 从余下的N - 1个元素中,找出关键字最小的元素,重复1、2步,直到排序结束。

三、代码实现

选择排序比较简单,以下是我自己的实现,跟官方版差不多,所以完全可以参考。

/**
 * 选择排序
 *
 * 1. 从待排序序列中,找到关键字最小的元素;
 * 2. 如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换;
 * 3. 从余下的`N - 1`个元素中,找出关键字最小的元素,重复①、②步,直到排序结束。
 *    仅增量因子为1时,整个序列作为一个表来处理,表长度即为整个序列的长度。
 * @param arr  待排序数组
 */
public static int[] selectionSort(int[] array) {
    //总共要经过N-1轮比较
    for (int i = 0; i < array.length - 1; i++) {
        int min = i;
        //每轮需要比较的次数
        for (int j = i + 1; j < array.length; j++) {  //选出之后待排序中值最小的位置
            if (array[j] < array[min]) {
                min = j;//记录目前能找到的最小值元素的下标
            }
        }
        //将找到的最小值和i位置所在的值进行交换
        if (i != min) {
            int temp = array[min];   //交换操作
            array[min] = array[i];
            array[i] = temp;
        }
        //第 i轮排序的结果为
        System.out.print("第" + (i + 1) + "轮排序后的结果为:");
        display(array);
    }
    return array;
}

//遍历显示数组
public static void display(int[] array) {
    for (int i = 0; i < array.length; i++) {
        System.out.print(array[i] + " ");
    }
    System.out.println();
}

public static void main(String[] args) {
    int[] array = {4, 2, 8, 9, 5, 7, 6, 1, 3};

    //未排序数组顺序为
    System.out.println("未排序数组顺序为:");
    display(array);
    System.out.println("-----------------------");
    array = selectionSort(array);
    System.out.println("-----------------------");
    System.out.println("经过选择排序后的数组顺序为:");
    display(array);
}

输出如下:

未排序数组顺序为:
4 2 8 9 5 7 6 1 3 
-----------------------
第1轮排序后的结果为:1 2 8 9 5 7 6 4 3 
第2轮排序后的结果为:1 2 8 9 5 7 6 4 3 
第3轮排序后的结果为:1 2 3 9 5 7 6 4 8 
第4轮排序后的结果为:1 2 3 4 5 7 6 9 8 
第5轮排序后的结果为:1 2 3 4 5 7 6 9 8 
第6轮排序后的结果为:1 2 3 4 5 6 7 9 8 
第7轮排序后的结果为:1 2 3 4 5 6 7 9 8 
第8轮排序后的结果为:1 2 3 4 5 6 7 8 9 
-----------------------
经过选择排序后的数组顺序为:
1 2 3 4 5 6 7 8 9 

四、性能分析

选择排序和冒泡排序执行了相同次数的比较:\(N *(N-1)/2\),但是至多只进行了N次交换。

N值很大时,比较次数是主要的,所以和冒泡排序一样,用大O表示是\(O(N^2)\)时间级别。但是由于选择排序交换的次数少,所以选择排序无疑是比冒泡排序快的。
N值较小时,如果交换时间比选择时间大的多,那么选择排序是相当快的。

以下是选择排序复杂度:

平均时间复杂度 最好情况 最坏情况 空间复杂度
O(n²) O(n²) O(n²) O(1)

选择排序的简单和直观名副其实,这也造就了它”出了名的慢性子”,无论是哪种情况,哪怕原数组已排序完成,它也将花费将近n²/2次遍历来确认一遍。即便是这样,它的排序结果也还是不稳定的。唯一值得高兴的是,它并不耗费额外的内存空间。

posted @ 2022-06-18 19:34  夏尔_717  阅读(113)  评论(0编辑  收藏  举报