07-选择排序

选择排序

1. 算法概述

选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。

2. 算法原理

  • 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
  • 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
  • 重复第二步,直到所有元素均排序完毕。

3. 动图演示

4. 代码实现

 @Test
public void sort() {
    int[] arr = new int[]{2, 7, 1, 4, 5, 3, 6};
    //从第一个开始,到最后一个,进行比较,总共能够执行 n - 1 次
    //每一趟执行完成后,都会选出一个相对最小的元素,排在已经排序好的元素后面
    for (int i = 0; i < arr.length - 1; i++) {
        //临时存储索引
        int min = i;
        //与之后的所有元素进行对比,然后选出一个相对最小的元素
        for (int j = i + 1; j < arr.length; j++) {
            if (arr[j] < arr[min]) {
                // 记录目前能找到的最小值元素的索引
                min = j;
            }
        }

        // 将找到的最小值和i位置所在的值进行交换
        if (i != min) {
            swap(arr, min, i);
        }
    }
    log.info("排序后:{}", JSON.toJSONString(arr));
}

5. 算法优化

对于每一趟,我们需要遍历一遍,将找到的最小的数放在应该出现的位置,所以,选择排序的时间复杂度是O(n²),不管是最好情况还是最坏情况,找最小数的过程都需要遍历一遍,所以,选择排序最好情况也是O(n²)。

优化方案:根据上边的分析,如果在每一次查找最小值的时候,也可以找到一个最大值,然后将两者分别放在它们应该出现的位置,这样遍历的次数就比较少了一半,下边给出代码实现:

@Test
public void sort1() {
    int[] arr = new int[]{1, 2, 7, 1, 4, 5, 3, 6};

    //左侧开始排序相对最小值,相对第一个下表,默认为0
    int left = 0;
    //右侧开始排序相对最大值,相对第一个坐标,默认为arr.length - 1
    int right = arr.length - 1;

    while (left < right) {
        //记录无序区最大元素下标、最小元素下标
        int max = left, min = left;

        //临时变量,记录当前操作元素的下标
        int temp = 0;
        //temp = left + 1 表示 <= left 已经排好序,在有序元素后一位开始,与最后一个有序元素对比
        //temp <= right 表示 >= right 已经排好序,不能超过该位置
        for (temp = left + 1; temp <= right; temp++) {
            //找最大元素下标
            if (arr[temp] < arr[min]) {
                min = temp;
            }
            //找最小元素下标
            if (arr[temp] > arr[max]) {
                max = temp;
            }
        }

        //min == left 则表示,本次找到的最小值就是当前位置,则没有必要交换
        if (min != left) {
            swap(arr, left, min);

            //【注意】如果最大元素是left, 上一步已经将 最小元素min 交换到 left位置,此时 min下标存储的是原left的元素
            if (max == left) {
                max = min;
            }
        }

        //max == right 则表示,本次找到的最大值就是当前位置,则没有必要交换
        if (max != right) {
            swap(arr, max, right);
        }

        //左右两侧指针向中间移动
        left++;
        right--;
    }
    log.info("排序后:{}", JSON.toJSONString(arr));
}

猜你喜欢

转载自blog.csdn.net/taodada007/article/details/89398184