排序算法-交换排序-冒泡排序

189 阅读3分钟

「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战

冒泡排序

介绍

冒泡排序 这个排序算法,可谓是经典,几乎提起排序算法,第一个想到的就是这个 冒泡排序算法 的名字。

  • 冒泡排序 的原理就是:

通过循环,依次比较相邻的两个数,如果第一个数大于第二个数,那么就进行交换操作。之后继续重复比较,交换,直到此次循环结束后,最大的值会在数组的最后一个。

依次类推,每次从第0个数开始,进行比较,交换操作,就是冒泡排序。

下面是动态图的一个演示

1391679-20180618163321525-1936669878.gif

步骤

冒泡排序算法 的步骤:

  • 需要双层循环

  • 外层循环从 i=0 开始,至数组的 len-1 处。[i,len-1)

  • 内层循环是从 j=0 开始,至数组的 len-i-1 处。[j,len-i-1)

  • 通过比较下标 j 和 j+1 对应数组的值大小,来判断是否交换

  • 最终得到 冒泡排序算法 的结果

代码

1.常规

const bubbleSort = arr => {
  console.time('耗时')
  const length = arr.length
  if (length <= 1) return;
  for (let i = 0; i < length - 1; i++) {
    for (let j = 0; j < length - i - 1; j++) {
      if(arr[j]>arr[j+1]){
        let temp = arr[j]
        arr[j]=arr[j+1]
        arr[j+1] = temp
      }
    }
  }
  console.log('改进前 arr :', arr);
  console.timeEnd('耗时');
}

const arr = [7, 8, 4, 5, 6, 3, 2, 1];
bubbleSort(arr);

可以注意到代码部分还是很简单,很容易理解的。但是细看,可以发现一个问题,我们比较的次数太多。

此时假设,数组为 [8, 1, 2, 3, 4, 5, 6, 7]

我们可能一眼就看出来了,只需要冒泡一次就可以得到排序结果,但是程序却执行了很多次,而且后面的操作都是没有任何实际意义的。这很显然,上面的代码不是最优解,还可以有更好的解决方案。就是外层循环后,查看内层循环是否有数据的一个交换操作。

  • 如果有,说明此时还不是最终结果

  • 如果没有,说明此时就已经是最终结果,不用继续后面的循环操作了,可以节省大量的排序时间。

2.优化

const bubbleSort = arr => {
  console.time('耗时')
  const length = arr.length
  if (length <= 1) return;
  for (let i = 0; i < length - 1; i++) {
    let hasChange = false; // 提前退出冒泡循环的标志位
    for (let j = 0; j < length - i - 1; j++) {
      if(arr[j]>arr[j+1]){
        let temp = arr[j]
        arr[j]=arr[j+1]
        arr[j+1] = temp
        hasChange = true; // 表示有数据交换
      }
    }
    if (!hasChange) break; // 如果 false 说明所有元素已经到位,没有数据交换,提前退出
  }
  console.log('改进前 arr :', arr);
  console.timeEnd('耗时');
}

const arr = [7, 8, 4, 5, 6, 3, 2, 1];
bubbleSort(arr);

通过对比,我们可以看到优化后的代码,添加了一个类似 flag 标志,查看是否进行了交换的一个操作。

通过判断,如果没有交换操作,我们可以通过 break 来提前退出循环,达到优化的一个步骤。

总结

冒泡排序算法 优缺点:

优点:易于理解,简单。

缺点:耗时,进行比较的次数较多。

注意 代码的优化部分理解