冒泡排序、选择排序

98 阅读4分钟

一.冒泡排序

代码示例

const inputArr = [5, 3, 8, 4, 2];
const handleBubbleSort = (arr) => {
    const maxIndex = arr.length -1;  //4
    for(let i = 0; i<= maxIndex-1;i++) {
      for(let j=0; j <= maxIndex - i -1 ;j++) {
        if(arr[j] > arr[j+1]) {
          [arr[j],arr[j+1]] = [arr[j+1],arr[j]]
        }
      }
    }
    return arr
}

const bubbleSortData = handleBubbleSort(inputArr);
console.log(bubbleSortData,'bubbleSortData')

总结:

  1. 总共两层比较,最外层比较arr.length - 1次,下标是从0开始;
  2. 内层比较:当i= 0时,相当于最外层的比较,因为最后一个比较值是比较项的倒数第二层,所以j<=maxIndex - i -1

二. 选择排序

function selectionSort(arr) {
  const len = arr.length-1;
  for(let i=0; i <= len-1;i++) {
    let minIndex = i;
    for(let j=i+1; j <=len;j++ ) {
      if(arr[j] < arr[minIndex]) {
        minIndex = j
      }
    }
    if(i !== minIndex) {
      [arr[minIndex],arr[i]] = [arr[i],arr[minIndex]]
    }
  }
  return arr
}

// 测试数组
const array = [64, 25, 12, 22, 11];
const sortedArray = selectionSort(array);
console.log(sortedArray,'123'); 

冒泡排序优化策略

  1. 提前终止排序
function optimizedBubbleSort1(arr) 
{ const len = arr.length; for (let i = 0; i < len; i++) 
{ let swapped = false; for (let j = 0; j < len - i - 1; j++) { if (arr[j] > arr[j + 1]) { [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; swapped = true; } } 
if (!swapped) { break; } }
return arr; }

难点梳理: 基础版实现(完整遍历)假如数组有n列,那就必须比较n-1轮,优化后,比如n=9;当轮询到第三轮时,如果发现没有交换位置,说明升序的数据已经是有序的了,就可以提前退出循环,就不要遍历后面的4、5、6、7、8轮

三、总结

冒泡排序和选择排序是两种简单但效率相对较低的排序算法。以下是它们的时间和空间复杂度的分析:

排序方式
  • 选择排序

    • 选择排序的核心思路是每一轮从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置(这里的起始位置指当前未排序部分的首位),然后再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾(从已排序序列自身看),也就是当前未排序部分的首位,以此类推,直到全部待排序的数据元素排完。
    • 例如对于数组 [5, 3, 8, 4, 2],第一轮会从整个数组中找到最小的元素 2,并将其与数组的第一个元素 5 交换位置,数组变为 [2, 3, 8, 4, 5]
  • 冒泡排序

    • 冒泡排序通过多次遍历数组,比较相邻的元素,如果顺序错误就把它们交换过来,每一轮遍历都会将最大(或最小)的元素 “冒泡” 到数组的末尾,经过多轮遍历后使整个数组有序。
    • 同样对于数组 [5, 3, 8, 4, 2],第一轮会比较 5 和 3,交换它们的位置,数组变为 [3, 5, 8, 4, 2],接着比较 5 和 8,位置不变,再比较 8 和 4,交换位置,数组变为 [3, 5, 4, 8, 2],继续比较 8 和 2,交换位置,数组变为 [3, 5, 4, 2, 8],这样最大的元素 8 就 “冒泡” 到了数组的末尾。

冒泡排序 (Bubble Sort)

时间复杂度

  • 最好情况: O(n) —— 当数组已经是有序的,冒泡排序在第一次遍历后就能确定数组已经有序,从而提前结束排序。
  • 最坏情况: O(n²) —— 当数组是逆序的,冒泡排序需要进行大量的元素交换。
  • 平均情况: O(n²) —— 在大多数情况下,冒泡排序需要进行接近最坏情况的比较和交换操作。

空间复杂度

  • O(1) —— 冒泡排序是原地排序算法,只需要一个常数级别的额外空间用于临时变量。

选择排序 (Selection Sort)

时间复杂度

  • 最好情况: O(n²) —— 选择排序无论数组是否已经有序,都需要进行 n-1 次选择操作,每次选择操作需要 O(n) 的时间。
  • 最坏情况: O(n²) —— 同最好情况,选择排序的时间复杂度在最坏情况下也是 O(n²)。
  • 平均情况: O(n²) —— 选择排序的时间复杂度在各种情况下都是 O(n²)。

空间复杂度

  • O(1) —— 选择排序同样是原地排序算法,只需要一个常数级别的额外空间用于临时变量。

总结

  • 冒泡排序 和 选择排序 的时间复杂度在最好、最坏和平均情况下都是 O(n²)。
  • 它们的空间复杂度都是 O(1)。