动图介绍排序算法之冒泡排序

1,507 阅读3分钟

概念

首先看一下维基百科对冒泡排序的定义:

冒泡排序(英语:Bubble Sort)又称为泡式排序,是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

算法的步骤如下(来自维基百科):

  • 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
  • 针对所有的元素重复以上的步骤,除了最后一个。
  • 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

概念和步骤看不懂?文字太多不想看?没关系,我们通过动图来看冒泡排序的流程,假设待排序数组为 [29,10,14,37,14]

第一趟排序

Aug-08-2021 15-03-52.gif

第一趟排序比较流程如下:

  • 29 和 10 比较,29 比 10 大,交换位置,此时数组为 [10,29,14,37,14]
  • 29 和 14 比较,29 比 14 大,交换位置,此时数组为 [10,14,29,37,14]
  • 29 和 37 比较,29 比 14 小,不需要交换,此时数组为 [10,14,29,37,14]
  • 37 和 14 比较,37 比 14 大,交换位置,此时数组为 [10,14,29,14,37]

第一趟排序结束,出现位置交换,需要进行第二趟排序。当前数组为 [10,14,29,14,37],待排序数组为 [10,14,29,14](37已有序)

第二趟排序

Aug-08-2021 15-16-27.gif

第二趟排序比较流程如下:

  • 10 和 14 比较,10 比 14 小,不需要交换,此时数组为 [10,14,29,14]
  • 14 和 29 比较,14 比 29 小,不需要交换,此时数组为 [10,14,29,14]
  • 29 和 14 比较,29 比 14 大,交换位置,此时数组为 [10,14,14,29]

第二趟排序结束,出现位置交换,需要进行第三趟排序。当前数组为 [10,14,14,29,37],待排序数组为 [10,14,14][29,37]已有序)

第三趟排序

Aug-08-2021 15-25-30.gif

第三趟排序比较流程如下:

  • 10 和 14 比较,10 比 14 小,不需要交换,此时数组为 [10,14,14]
  • 14 和 14 比较,不需要交换,此时数组为 [10,14,14]

至此第三趟排序结束,没有位置交换,冒泡排序结束,[10,14,14,29,37] 为最终有序数列

JavaScript代码实现

function bubbleSort(arr) {
    const len = arr.length
    let exchange = false // 标识是否有数据交换
    for (const i = 0; i < len - 1; i++) {
        exchange = false
        for (const j = 0; j < len - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                exchange = true
                // 交换位置
                const temp = arr[j + 1]
                arr[j + 1] = arr[j]
                arr[j] = temp
            }
        }
        if (!exchange) return arr // 没有数据位置交换,提前结束,返回数组
    }
    return arr
}

复杂度分析

当数组已经有序时,一个循环下来没有位置交换,排序结束,时间复杂度为 O(n)

当数组是逆序时,内循环一共要执行 (n-1)+(n-2)+...+1=n*(n-1)/2,即时间复杂度为 O(n2)

总结

冒泡排序是最简单的排序算法之一,也是笔者开启排序算法篇章中的第一篇,后续还会继续更新快速排序、堆排序、归并排序等算法,敬请期待~