JavaScript算法 - 冒泡排序

冒泡排序(从小到大)

js 复制代码
/**
* 文字描述,毕竟不如口语表达,所以,这里有一些帮助阅读的方法
* 释义:
*    项:"数组的 0 项",指的是数组 index 为 0 的值
*
* tips:
* 1. 将会用到的数组,都是复杂度最高的数组,也就是原始排序为 [3,2,1] 这样从大到小的数组,有助于直观理解
* 2. 如果觉得有点乱,就关注函数返回的结果。上一步结果,就是我们下一步的根本
*/
如果数组一共有两项
js 复制代码
  const myArr = [9, 8]
  const mySort = (arr) => {
    if (arr[0] > arr[1]) {
      ;[arr[0], arr[1]] = [arr[1], arr[0]]
    }
    return arr
  }
  const result = mySort(myArr)
  console.log(result, 'result') // [ 8, 9 ]

此时数组变为:[ 8, 9 ] 总结:以上是最简单的排序。数组只有两项,0 项和 1 项。比大小、换位,没了

如果有三个呢
js 复制代码
  const myArr = [9, 8, 7]
  const mySort = (arr) => {
    if (arr[0] > arr[1]) {
      ;[arr[0], arr[1]] = [arr[1], arr[0]]
    }
    return arr
  }
  const result = mySort(myArr)
  console.log(result, 'result')// [ 8, 9, 7 ]

此时的数组变为:[ 8, 9, 7 ]

看着这个数组,总结:预料之中,0 项和 1 项换位。接下来呢?

排序后数组的含义可以解释为:

可以确定:数组的 1 项,是数组 0 项、1 项中的的最大值

不能确定:数组的 2 项,更大还是更小

!那么,让数组的 1、2 项比大小,就确定了数组中最大的是谁

代码延申
js 复制代码
  const myArr = [9, 8, 7]
  const mySort = (arr) => {
    // 第一步
    if (arr[0] > arr[1]) {
      ;[arr[0], arr[1]] = [arr[1], arr[0]]
    }
    // 走到此处,arr 的值为 [ 8, 9, 7 ]

    // 第二步
    if (arr[1] > arr[2]) {
      ;[arr[1], arr[2]] = [arr[2], arr[1]]
    }
    // 走到此处,arr 的值为 [ 8, 7, 9 ]
    return arr
  }
  const result = mySort(myArr)
  console.log(result, 'result') // [ 8, 7, 9 ]

此时的数组变为:[ 8, 7, 9 ]

看着这个数组,总结:延申后,我们确定了最大值,且移动到了最右边

希望这里,你会感受到思路在变清晰

排序后的数组含义可以解释为

可以确定:0 项和 1 项,都比 2 项小。2 项,是数组的最大值

不能确定:数组的 0 项、1 项,谁大

!那么,让数组的 0、1 项比大小。(因为已经确定了 2 项最大,那么,确定了 0、1 的大小关系,就确定了全部的大小关系)

代码再延申
js 复制代码
  const mySort = (arr) => {
    // 第一步
    if (arr[0] > arr[1]) {
      ;[arr[0], arr[1]] = [arr[1], arr[0]]
    }
    // 走到此处,arr 的值为 [ 8, 9, 7 ]

    // 第二步
    if (arr[1] > arr[2]) {
      ;[arr[1], arr[2]] = [arr[2], arr[1]]
    }
    // 走到此处,arr 的值为 [ 8, 7, 9 ]

    // 第三步(与 第一步 完全一致)
    if (arr[0] > arr[1]) {
      ;[arr[0], arr[1]] = [arr[1], arr[0]]
    }
    // 走到此处,arr 的值为[ 7, 8, 9 ]
    return arr
  }
  const result = mySort(myArr)
  console.log(result, 'result') // [ 7, 8, 9 ]

此时的数组变为:[ 7, 8, 9 ],是我们要的结果

思路总结:

markdown 复制代码
我们排序的方式为:  
    0、1 对比换位,1、2 对比换位,确定 2  
    0、1 对比换位,确定 0、1  

思路扩展:

markdown 复制代码
尝试想象一下,当数组的数量为四个
    0、1 对比换位,1、2 对比换位,2、3 对比换位,确定 3
然后再重复一下刚刚实现的经过
    0、1 对比换位,1、2 对比换位,确定 2
    0、1 对比换位,确定 0、1
至此,一种算法入门的排序思路已经出现,它被称为:冒泡排序 ~咕嘟咕嘟

根据思路扩展,尝试实现算法:

js 复制代码
// 首先,写出第一轮循环对比:得到数组中最大值并移动到最右边
  const arr = [9, 8, 7, 6]
  const bubbleSort = (arr) => {
    // 先把之前的对比的判断,把索引改成动态的
    // if (arr[i] > arr[i + 1]) {
    //   ;[arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]
    // }
    
    // 首先想到for循环。能写出来什么样呢
    // for()
    // 我们需要用一些数字。跟循环的次数有关
    // 一般而言,都会拿数组的长度来用。这里,数组的长度有什么用处
    // arr.length // 4
    // for (let i = 0; i < ???; i++) {
    //   if (arr[i] > arr[i + 1]) {
    //       ;[arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]
    //     }
    // }
    
    // 关键是,i 要小于几呢?那就先要确定,我们要对比多少次,然后再给出限制
    // 这个对比的次数,要依据 < 思路扩展 > 中的第一轮对比!其中第一轮,经过了 3 次对比换位
    // 又因为我们是从 0 开始的。所以,要拿到的数字是0、1、2,所以要小于3
    // 数组的长度跟这个数字的关系就是 length - 1,这就是我们要小于的值
    for (let i = 0; i < arr.length - 1; i++) {
      if (arr[i] > arr[i + 1]) {
        ;[arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]
      }
    }
    return arr
    // 如果从 1 开始,那就另一回事了
  }
  console.log(bubbleSort(arr)) // [ 8, 7, 6, 9 ]

这时候我们已经把最大的移动到了最右边,第一步完成了

然后呢?接下来,我们要对比前三个,不对比第四个了。这个怎么写啊

我们要让这个循环再来一遍。但是,循环次数要少一次。重要!!!

让循环再来一次,也就是说,让这个循环循环

js 复制代码
  const bubbleSort = (arr) => {
    // for()
    // 外边这个循环怎么加呢,要让里面的循环,走几轮呢?跟里面的循环有什么关系呢?
    // 再一次,依据 < 思路扩展 > ,要让里面循环 3 轮,就能得到结果了
    // 里面循环对比的次数不断减 1 的,那让外面的循环不断减 1,并让这个数字同步到里面对 i 的限制
    // for(let j = ???; j >= 0; j--){
    //    for (let i = 0; i < arr.length - 1; i++) {
    //      if (arr[i] > arr[i + 1]) {
    //        ;[arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]
    //      }
    //    }
    // }
    // 让外面的 j ,设定为里面的 i 的初始值,然后逐渐变小,最终等于 0,然后结束
    for (let j = arr.length - 1; j >= 0; j--) {
      for (let i = 0; i < j; i++) {
        if (arr[i] > arr[i + 1]) {
          ;[arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]
        }
      }
    }
    return arr
  }
  console.log(bubbleSort(arr)) // [ 6, 7, 8, 9 ]
主线代码完成
js 复制代码
  const bubbleSort = (arr) => {
    for (let j = arr.length - 1; j >= 0; j--) {
      for (let i = 0; i < j; i++) {
        if (arr[i] > arr[i + 1]) {
          ;[arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]
        }
      }
    }
    return arr
  }
// 随便输入一些,看看效果
console.log(bubbleSort([543, 4, 76, 524, 24, 65, 23, 235, 3245])) // [ 4, 23, 24, 65, 76, 235, 524, 543, 3245 ]
后续优化:隔离数据源、减少非必要性能开销
js 复制代码
  const bubbleSort = (array) => {
    const arr = [...array]
    for (let j = arr.length - 1; j >= 0; j--) {
      let swapped = false
      for (let i = 0; i < j; i++) {
        if (arr[i] > arr[i + 1]) {
          ;[arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]
          swapped = true
        }
      }
      if (!swapped) break
    }
    return arr
  }

完成。

相关推荐
仍然.7 小时前
JavaDataStructure---排序
数据结构·算法·排序算法
曹自标14 小时前
workflow 拓扑排序算法
windows·算法·排序算法
zaiyang遇见1 天前
【基础排序】USACO Bronze 2016 January - Angry Cows
排序算法·模拟·信息学奥赛·程序设计竞赛·函数封装·usaco
星火开发设计1 天前
堆排序原理与C++实现详解
java·数据结构·c++·学习·算法·排序算法
星火开发设计2 天前
折半插入排序原理与C++实现详解
java·数据结构·c++·学习·算法·排序算法·知识
胖咕噜的稞达鸭3 天前
算法日记:分治-快排(颜色分类,排序数组,数组中的第k个最大元素 面试题17.14.最小k个数)
数据结构·算法·排序算法
小尧嵌入式4 天前
c++红黑树及B树B+树
开发语言·数据结构·c++·windows·b树·算法·排序算法
tobias.b4 天前
408真题解析-2009-10-数据结构-排序
数据结构·算法·排序算法·408考研·408真题·真题解析
Super小白&4 天前
十大经典排序算法详解(附C语言实现+复杂度分析)
c语言·算法·排序算法