选择排序

100 阅读2分钟

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

算法描述

  1. 在一个长度为 N 的无序数组中,第一次遍历 n-1 个数找到最小的和第一个数交换。
  2. 第二次从下一个数开始遍历 n-2 个数,找到最小的数和第二个数交换。
  3. 重复以上操作直到第 n-1 次遍历最小的数和第 n-1 个数交换,排序完成。

代码实现

static void SelectSort(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        int minPos = i;
        for (int j = i + 1; j < arr.length; j++) {
            minPos = arr[j] < arr[minPos] ? j : minPos;
        }
        swap(arr, minPos, i);
    }
    print(arr);
}

static void swap(int[] arr, int i, int j){
    int temp = arr[j];
    arr[j] = arr[i];
    arr[i] = temp;
}

static void print(int[] arr){
    for(int i = 0; i < arr.length; i++){
        System.out.print(" " + arr[i]);
    }
    System.out.println();
}

注意点

  1. 外循环的 i 之所以要小于 arr.length - 1 ,是因为内循环是从 i + 1 开始的,防止越界。不减一也不会报错,但最好有。
  2. 每次找到比 minPos 位置上的数还小的数时,记录他的角标,最后直接交换两个角标下的值,而不是每次找到就交换一次。

优化思路

最简单的选择排序是每次循环找到最小值与窗口最前面的值做交换。我们可以在循环的时候同时找到最大值,与窗口最后面的值做交换,这样就会节约一半时间。

优化代码实现

static void SelectSort2(int[] arr) {
   for (int i = 0; i < arr.length - i; i++) {
        intminPos = i;
        int maxPos = arr.length - i - 1;
        for (int j = i; j < arr.length - i; j++) {
            minPos = arr[j] < arr[minPos] ? j : minPos;
            maxPos = arr[j] > arr[maxPos] ? j : maxPos;
        }
        if (maxPos == i && minPos != arr.length - i - 1 ){
            swap(arr, maxPos, arr.length - i - 1);
            swap(arr, minPos, i);
        } else if (minPos == arr.length - i - 1 && maxPos == i) {
            swap(arr, minPos, i);
        } else{
            swap(arr, minPos, i);
            swap(arr, maxPos, arr.length - i - 1);
        }
    }
    print(arr);
}

注意点

  1. 每次都是同时找到最大值和最小值并交换。所以每次循环选择的窗口,前后的边界都需向中间收一格。
for (int i = 0; i < arr.length - i; i++)
  1. 可能出现最大值在左边界上的情况,所以每次循环须从左边界开始。
for (int j = i; j < arr.length - i; j++)
  1. 可能出现最大值在左边界,最小值在右边界的情况,此时只需一次交换。以及分别出现最小值在右边界和最大值在左边界的两种情况,需要注意交换顺序。
if (maxPos == i && minPos != arr.length - i - 1 ){
 	swap(arr, maxPos, arr.length - i - 1);
    swap(arr, minPos, i);
} else if (minPos == arr.length - i - 1 && maxPos == i) {
    swap(arr, minPos, i);
} else{
    swap(arr, minPos, i);
    swap(arr, maxPos, arr.length - i - 1);
}