Skip to content

选择排序

选择排序(selection sort)的工作原理非常简单:开启一个循环,每轮从未排序区间选择最小的元素,将其放到已排序区间的末尾。

设数组的长度为 n ,选择排序的算法流程如下图所示。

  1. 初始状态下,所有元素未排序,即未排序(索引)区间为 [0, n-1]
  2. 选取区间 [0, n-1] 中的最小元素,将其与索引 0 处的元素交换。完成后,数组前 1 个元素已排序。
  3. 选取区间 [1, n-1] 中的最小元素,将其与索引 1 处的元素交换。完成后,数组前 2 个元素已排序。
  4. 以此类推。经过 n - 1 轮选择与交换后,数组前 n - 1 个元素已排序。
  5. 仅剩的一个元素必定是最大元素,无须排序,因此数组排序完成。

选择排序步骤

tab image

在代码中,我们用 k 来记录未排序区间内的最小元素:

java
/* 选择排序 */
void selectionSort(int[] nums) {
    int n = nums.length;
    // 外循环:未排序区间为 [i, n-1]
    for (int i = 0; i < n - 1; i++) {
        // 内循环:找到未排序区间内的最小元素
        int k = i;
        for (int j = i + 1; j < n; j++) {
            if (nums[j] < nums[k])
                k = j; // 记录最小元素的索引
        }
        // 将该最小元素与未排序区间的首个元素交换
        int temp = nums[i];
        nums[i] = nums[k];
        nums[k] = temp;
    }
}
javaScript
/**
 * 选择排序
 * @param {Array} arr
 */
function sort(arr) {
  let N = arr.length;
  for (let i = 0; i < N; i++) {
    let min = i;
    //找内层循环的最小元素的索引
    for (let j = i + 1; j < N; j++) {
      if (arr[j] < arr[min]) {
        min = j;
      }
    }
    //在外层循环中,和当前数组最前面的元素交换
    let m = arr[i];
    arr[i] = arr[min];
    arr[min] = m;
  }
  return arr;
}

算法特性

  • 时间复杂度为 O(n^2)、非自适应排序:外循环共 n - 1 轮,第一轮的未排序区间长度为 n ,最后一轮的未排序区间长度为 2 ,即各轮外循环分别包含 nn - 132 轮内循环,求和为
  • 空间复杂度为 O(1)、原地排序:指针 ij 使用常数大小的额外空间。
  • 非稳定排序:如下图所示,元素 nums[i] 有可能被交换至与其相等的元素的右边,导致两者的相对顺序发生改变。

选择排序非稳定示例

粤ICP备20009776号