排序算法-选择排序(Selection Sort)

原理

  1. 从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置。
  2. 从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。
  3. 以此类推,直到全部待排序的数据元素的个数为零。

算法分析

  • 时间复杂度 :O(n^2)
  • 空间复杂度:O(1)

算法实现

selectionSort = (arr) => {
  // 判断边界
  if (arr == null || arr.length < 2) {
    return;
  }
  for (let i = 0; i < arr.length; i++) {
    let minIndex = i
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[i] > arr[j]) {
        minIndex = j
      }
    }
    if (i != minIndex) {
      swap(arr, i, minIndex)
    }
  }
  return arr
}
// 交换位置
swap = (arr, i, j) =>{
  let temp = arr[i]
  arr[i] = arr[j]
  arr[j] = temp
}
// let arr = [1, 4, 2, 3, 5, 9, 7, 8, 0]
let arr = [ 0, 1, 2, 3, 4, 5, 7, 8, 9]
console.log(selectionSort(arr))

优化

之前遍历一次只是找出了最小值或者最大值,若是一次将最大值和最小值全都找出,是不是就节省了遍历次数,虽然复杂度仍然是O(n^2),但是时间会减少,请看以下代码

selectionSort1 = (arr) => {
  // 判断边界
  if (arr == null || arr.length < 2) {
    return;
  }
  let left = 0
  let right = arr.length - 1;
  while (left < right) {
    // 假设最大值和最小值
    let minIndex = left
    let maxIndex = right
    for (let i = left; i <= right; i++) {
      // 若当前索引值比最小值还要小,则更新最小值索引
      if (arr[i] < arr[minIndex]) {
        minIndex = i
      }
      // 若当前索引值比最大值还要大,则更新最大值索引
      if (arr[i] > arr[maxIndex]) {
        maxIndex = i
      }
    }
    // 当前循环最大值索引和最小值索引分别为maxIndex,minIndex
    // 先交换最小值
    if (minIndex != left) {
      swap(arr, minIndex, left)
    }

    // 若最小值交换前最大值在left处时,即left是最大值maxIndex,
    // 但是由于第一次最小值交换,将真正的最小值放入left处,而left处的最大值被放到了交换前最小值处minIndex,最大值被掉包了
    // left索引值此时并不是最大值了,因此,需要重新将最小值赋值给最大值
    if (left == maxIndex) {
      maxIndex = minIndex
    }
    // 交换最大值
    if (maxIndex != right) {
      swap(arr, maxIndex, right)
    }

    left++
    right--
    console.log(arr);
  }

  return arr
}

优化的难点
在交换了最小值后,之前的排列已经不稳定了,原本索引对应的值都已经发生变化,若直接交换最大值,可能造成真正的最大值最小值掉包,请看下面分析

let arr = [11, 0, 1, 2, 3, 4, 5, 7, 8, 9]
//上面数组中最大值在第一个位置,此时假设最小值索引是0,最大值索引是9.
//经过第一轮循环后,找出最小值索引是1,最大值索引是0.
//接着进行最小值交换,将索引1的值放到索引0处,索引0处的值放到了索引1处。
//但是此时最大值的索引仍然指向0,然而经过了最小值交换后,索引0处的值并不是了最小值,最小值被放到了索引1处,
//因此在交换最大值前,需要先重新赋值最大值索引,将现在的最小值索引(经过最小值交换后的)赋值给最大值索引。
//最后进行最大值赋值就没有问题了
//后面的循环也是这个意思
//用大白话就是进行最大值交换时的最大值已经被最小值掉包了,需要重新找回真正的最大值

欢迎大脚一起来交流!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值