概念
首先看一下维基百科对冒泡排序的定义:
冒泡排序(英语:Bubble Sort)又称为泡式排序,是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
算法的步骤如下(来自维基百科):
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
概念和步骤看不懂?文字太多不想看?没关系,我们通过动图来看冒泡排序的流程,假设待排序数组为 [29,10,14,37,14]:
第一趟排序
第一趟排序比较流程如下:
- 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已有序)
第二趟排序
第二趟排序比较流程如下:
- 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]已有序)
第三趟排序
第三趟排序比较流程如下:
- 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)。
总结
冒泡排序是最简单的排序算法之一,也是笔者开启排序算法篇章中的第一篇,后续还会继续更新快速排序、堆排序、归并排序等算法,敬请期待~