「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」
冒泡排序
介绍
冒泡排序 这个排序算法,可谓是经典,几乎提起排序算法,第一个想到的就是这个 冒泡排序算法 的名字。
冒泡排序的原理就是:
通过循环,依次比较相邻的两个数,如果第一个数大于第二个数,那么就进行交换操作。之后继续重复比较,交换,直到此次循环结束后,最大的值会在数组的最后一个。
依次类推,每次从第0个数开始,进行比较,交换操作,就是冒泡排序。
下面是动态图的一个演示
步骤
冒泡排序算法 的步骤:
-
需要双层循环
-
外层循环从 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 来提前退出循环,达到优化的一个步骤。
总结
冒泡排序算法 优缺点:
优点:易于理解,简单。
缺点:耗时,进行比较的次数较多。
注意 代码的优化部分理解