1. 简介

本文我们将学习 选择排序(Selection Sort),并通过 Java 实现它,同时分析其性能表现。

选择排序是一种简单但效率不高的排序算法,适用于小规模数据集。它通过重复“找出未排序部分的最小元素并放到前面”的方式逐步构建有序序列。

2. 算法概述

选择排序的基本思想是:

  • 从数组的第一个元素开始,扫描整个数组,找出最小的元素;
  • 将该最小元素与第一个元素交换位置;
  • 接着从第二个元素开始重复上述过程,找出剩余部分中最小的元素,并与第二个元素交换;
  • 依此类推,直到倒数第二个元素。

最终,最后一个元素自然就在正确位置上,整个数组完成排序。

一句话总结:每次找最小,放到正确位置,逐步构建有序序列。

如果是降序排列,则每次找的是最大元素。

2.1. 示例演示

我们以一个未排序数组为例:

int[] arr = {5, 4, 1, 6, 2};

第一轮迭代:

  • 当前位置:索引 0,值为 5;
  • 扫描剩余元素,找到最小值 1;
  • 与索引 0 位置的元素交换。

结果数组变为:

{1, 4, 5, 6, 2}

比较次数:4次

第二轮迭代:

  • 当前位置:索引 1,值为 4;
  • 扫描剩余元素,找到最小值 2;
  • 与索引 1 位置的元素交换。

结果数组变为:

{1, 2, 5, 6, 4}

比较次数:3次

第三轮迭代:

  • 当前位置:索引 2,值为 5;
  • 找到最小值 4;
  • 与索引 2 位置交换。

结果:

{1, 2, 4, 6, 5}

比较次数:2次

第四轮迭代:

  • 当前位置:索引 3,值为 6;
  • 找到最小值 5;
  • 与索引 3 位置交换。

最终排序结果:

{1, 2, 4, 5, 6}

比较次数:1次

3. Java 实现

下面是使用双重循环实现的选择排序代码:

3.1. 升序排序

public static void sortAscending(final int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        int minElementIndex = i;
        for (int j = i + 1; j < arr.length; j++) {
            if (arr[minElementIndex] > arr[j]) {
                minElementIndex = j;
            }
        }

        if (minElementIndex != i) {
            int temp = arr[i];
            arr[i] = arr[minElementIndex];
            arr[minElementIndex] = temp;
        }
    }
}

3.2. 降序排序

public static void sortDescending(final int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        int maxElementIndex = i;
        for (int j = i + 1; j < arr.length; j++) {
            if (arr[maxElementIndex] < arr[j]) {
                maxElementIndex = j;
            }
        }

        if (maxElementIndex != i) {
            int temp = arr[i];
            arr[i] = arr[maxElementIndex];
            arr[maxElementIndex] = temp;
        }
    }
}

⚠️ 注意:以上实现都使用了“选择最小/最大”+“交换”的方式,避免频繁移动元素。

如果想更灵活地控制排序方式,可以结合 Java 的 Comparator 接口实现泛型版本。

4. 性能分析

4.1. 时间复杂度

我们来计算一下总共做了多少次比较:

  • 第一轮比较 n-1 次;
  • 第二轮比较 n-2 次;
  • ...
  • 最后一轮比较 1 次。

总共比较次数为:

(n-1) + (n-2) + ... + 1 = (n-1)*n / 2

简化后为:

O(n²)

✅ 所以选择排序的时间复杂度是 **O(n²)**,不管输入数据是否已经部分有序,都需要进行这么多轮比较。

4.2. 空间复杂度

选择排序只使用了一个临时变量用于交换元素,因此空间复杂度为:

O(1)

✅ 是一个原地排序算法,占用空间非常小。

5. 总结

选择排序的优点:

  • ✅ 实现简单;
  • ✅ 原地排序,空间占用小;
  • ✅ 不依赖数据分布,适用于小数据集。

缺点:

  • ❌ 时间复杂度为 O(n²),性能较差;
  • ❌ 无法提前终止,即使数组已经有序,也要完成所有遍历;
  • ❌ 不稳定排序(相同元素的位置可能改变)。

在实际开发中,如果你面对的是大数据量,建议使用更高效的排序算法,如快速排序、归并排序或 Java 自带的 Arrays.sort()

完整代码示例可参考:GitHub 示例仓库(示例链接,非真实地址)


原始标题:Selection Sort in Java