前言:
在JavaScript中,冒泡排序是一种简单直观的排序算法,但在实际应用中可能会因为效率较低而不够理想。针对冒泡排序的效率问题,我们可以进行一些优化,以提高算法的执行效率。下面将给出的两种优化方案,分别进行详细解释。
冒泡排序
代码思路
ruby
//冒泡排序过程
//经过多轮比较使每词将最大的数字排序到后面
// 5 8 6 3 9 2 1 7
// 5 6 3 8 2 1 7 9 //因为最后的数字一定是最大的,且逐渐增加,所以此处无需再比较(优化2)
// 5 3 6 2 1 7 8 9
// 3 5 2 1 6 7 8 9
// 3 1 2 5 6 7 8 9 //实际上从此处已经排序好了,后面的可以去掉优化空间(优化1)
// 1 2 3 5 6 7 8 9
// 1 2 3 5 6 7 8 9
// 1 2 3 5 6 7 8 9
代码实现
ini
//冒泡排序
function bubbleSort(arr) {
console.time('冒泡排序'); //计时方法,计算从开始排序到排序结束所花费时间
const length = arr.length;
for (let i = 0; i < length - 1; i++) {
for (let j = 0; j < length - i - 1; j++) {
if (arr[j] > arr[j+1]) {
[arr[j], arr[j+1]] = [arr[j+1], arr[j]];
}
}
}
console.timeEnd('冒泡排序')
return arr;
}
const arr = [5, 8, 6, 3, 9, 2, 1, 7];
console.log(bubbleSort(arr));
优化方案一
优化思路
在传统的冒泡排序中,即使数组已经部分有序,仍然需要执行完所有的比较操作,这显然是不必要的。因此,我们可以引入一个标记isSorted,来判断当前轮次是否有数据交换,如果没有则说明数组已经有序,可以提前结束排序。
代码实现
ini
//优化冒泡排序1.0
function bubbleSort1(arr) {
console.time('改进冒泡排序');
const length = arr.length;
if (length <= 1) return;
for (let i = 0; i < length - 1; i++) {
let isSorted = true; //后面排序不再比较时的跳转关键标记
for (let j = 0; j < length - i -1; j++) {
if (arr[j] > arr[j+1]) {
[arr[j] , arr[j+1]] = [arr[j+1], arr[j]];
isSorted = false;//发生排序交换时,标记变为false
}
}
if (isSorted) { //当标记为true时则说明此时排序不再进行比较,意为排序已经完成可提前截至
break;
}
}
console.timeEnd('改进冒泡排序')
return arr
}
console.log(bubbleSort1(arr))
优化效果
通过引入isSorted
标志位,能够在部分有序的情况下提前结束排序,从而减少了不必要的比较次数和交换次数,提高了排序的效率。
优化方案二
优化思路
在第一种优化的基础上,我们可以进一步减少每轮比较的次数。因为在每一轮排序过程中,最后一次发生数据交换的位置之后的数据已经是有序的,因此可以将此位置作为下一轮比较的边界,减少不必要的比较操作。
代码实现
ini
//优化冒泡排序2.0
// 数组的最右边,是已经排好序的,所以不需要比较 j-i-1的
// 标记上一轮,完成交换的最后一次的位置,最后的位置 < j-i-1
const bubbleSort2 = (arr) => {
console.time('改进冒泡排序2.0');
let tmp = 0;
let lastExchangeIndex = 0;
let arrLen = arr.length;
let sortBorder = arrLen - 1;
for (let i = 0; i < arrLen - 1; i++) {
let isSorted = true;
for (let j = 0; j < sortBorder; j++) {
if (arr[j] > arr[j+1]) {
[arr[j], arr[j+1]] = [arr[j+1], arr[j]]
isSorted = false;
lastExchangeIndex = j;
//因为最后的数字一定是最大的,且逐渐增加,所以sortBorder后面无需再比较
}
}
sortBorder = lastExchangeIndex
if (isSorted) {
break;
}
}
console.timeEnd('改进冒泡排序2.0')
return arr
}
const arr = [5, 8, 6, 3, 9, 2, 1, 7];
console.log(bubbleSort2(arr))
优化效果
在每一轮排序过程中,通过sortBorder
记录上一轮完成数据交换的位置,在下一轮比较时只需比较到该位置即可,避免了对已经有序的部分重复的比较操作,进一步提高了排序效率。
结果比较

可以看出每次优化所花费时间逐渐减少。
总结
通过以上两种优化方案,我们成功地提高了冒泡排序的执行效率。在实际开发中,根据不同的数据情况选择合适的优化方式,可以更好地应用冒泡排序算法,并且理解这些优化点也有助于我们对排序算法的理解和应用。