用javascript实现冒泡排序(包含双向冒泡排序)

549 阅读2分钟

一、简介

  • 时间复杂度:O(n²)
  • 空间复杂度:O(1)
  • 是否稳定:是
  • 优点:空间复杂度较低,稳定, 简单
  • 缺点:时间复杂度太高,效率低

二、核心思想

  • 外层循环每次找到一个最值(最大或者最小)
  • 内层循环进行相邻元素比较

三、排序过程动图

黄色:每轮找到的最大值
绿色:对比的相邻元素

冒泡排序.gif

四、代码实现

代码地址:github.com/shubenwumin…

通用函数

// 位置交换
const change = function (arr, index1, index2){
  [arr[index1], arr[index2]] = [arr[index2], arr[index1]];
}

版本一:普通版

普通版本其实没什么好说的,就是每轮通过 相邻元素 间的比较找到一个 最值

const bubbleSort1 = function (arr) {
  let length = arr.length;
  // 此循环每次找到一个最值
  for (let i = 0; i < length - 1; i++) {
    // 此循环进行每轮的相邻元素比较
    for (let j = 0; j < length - 1 - i; j++) {
      if(arr[j] > arr[j+1]) {
        change(arr, j, j+1)
      }
    }
  }
  return arr;
}

版本二:检查版

这个版本其实是版本一的优化版。如果已经排好序了,是否还需要进行比较。那么问题来了,如何判定排序完成?其实很简单。当一轮相邻比较中都没有位置交换,说明已经完成排序。

const bubbleSort2 = function (arr) {
  let length = arr.length;
  // 此循环每次找到一个最值
  for (let i = 0; i < length - 1; i++) {
    // 本轮比较是否进行了位置交换
    let isChange = false;
    
    // 此循环进行每轮的相邻元素比较
    for (let j = 0; j < length - 1 - i; j++) {
      if(arr[j] > arr[j+1]) {
        change(arr, j, j+1)
        
        // 进入了这个if语句,说明进行了位置交换
        isChange = true;
      }
    }
    // 本轮没有进行位置交换,说明排序完成
    if(!isChange) {
      return arr;
    }
  }
  return arr;
}

版本三: 双向冒泡排序(相比于前两种,数据量越大排序越快)

此版本与另外两个版本的思想不同之处在于,它是每轮确定两个最值,一个最大值,一个最小值

const bubbleSort3 = function (arr) {
  let small = 0;
  let large = arr.length;
  while(small < large) {
    // 该轮是否发生位置交换
    let isChange = false;
      
    // 找大值
    for(let i = small; i < large - 1; i++) {
      if(arr[i] > arr[i+1]) {
          change(arr, i, i+1);
          isChange = true;
       }
    }
    large--;
    // 找小值
    for(let j = large - 1; j > small; j--) {
      if(arr[j] < arr[j-1]) {
        change(arr, j, j-1);
        isChange = true;
      }
    }
    small++;
    // 未发生位置交换
    if(!isChange) {
      return arr;
    }
  }
  
  return arr;
}