冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法
冒泡排序的思想就是在每次遍历一遍未排序的数列之后,将一个数据元素浮上去(也就是排好了一个数据)
如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”
冒泡排序的效率:
对上图7个数据的比较次数是:6 + 5 + 4 + 3 + 2 + 1
则对于n个数据,比较次数为 (n-1) + (n-2) + (n-3) + 1
= n * (n-1)/2
= 1/2 * n² - 1/2 * n
T(n) = 1/2 * n² - 1/2 * n = O(n²)
在最坏的情况下,每次比较之后都需要交换位置,此时时间复杂度为O(n²)
# 1. 实现冒泡排序
如果要实现一个从小到大的排序,算法原理如下:
- 首先比较相邻的元素,如果第一个元素比第二个元素大,则交换它们
- 针对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对,这样,最后的元素回事最大的数
- 针对所有的元素重复以上的步骤,除了最后一个
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
function bubbleSort(arr) {
const len = arr.length;
//外层循环控制冒泡趟数
for (let i = 0; i < len - 1; i++) {
//内层循环控制每趟比较的次数
for (let j = 0; j < len - 1 - i; j++) { //每次循环结束都把数值最高的排到后面
if (arr[j] > arr[j+1]) { // 相邻元素两两对比
var temp = arr[j+1]; // 元素交换
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 优化
对冒泡排序常见的改进方法是加入一标志性变量exchange
,用于标志某一趟排序过程中是否有数据交换
如果进行某一趟排序时并没有进行数据交换,则说明数据已经按要求排列好,可立即结束排序,避免不必要的比较过程
可以设置一标志性变量pos
,用于记录每趟排序中最后一次进行交换的位置,由于pos
位置之后的记录均已交换到位,故在进行下一趟排序时只要扫描到pos
位置即可,如下:
function bubbleSort1(arr){
const i=arr.length-1; //初始时,最后位置保持不变
while(i>0){
let pos = 0; //每趟开始时,无记录交换
for(let j = 0; j < i; j++){
if(arr[j] > arr[j+1]){
let tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
pos = j; //记录最后交换的位置
}
}
i = pos; //为下一趟排序作准备
}
return arr;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
在待排序的数列有序的情况下,只需要一轮排序并且不用交换,此时情况最好,时间复杂度为O(n)
并且从上述比较中看到,只有后一个元素比前面的元素大(小)时才会对它们交换位置并向上冒出,对于同样大小的元素,是不需要交换位置的,所以对于同样大小的元素来说,相对位置是不会改变的,因此, 冒泡排序是稳定的
# 2. 应用场景
冒泡排的核心部分是双重嵌套循环, 时间复杂度是 O(n²)
,相比其它排序算法,这是一个相对较高的时间复杂度,一般情况不推荐使用。