JavaScript冒泡排序算法优化详解

前言:

在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记录上一轮完成数据交换的位置,在下一轮比较时只需比较到该位置即可,避免了对已经有序的部分重复的比较操作,进一步提高了排序效率。

结果比较

可以看出每次优化所花费时间逐渐减少。

总结

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

相关推荐
烛阴9 小时前
从0到1掌握盒子模型:精准控制网页布局的秘诀
前端·javascript·css
码小凡12 小时前
优雅!用了这两款插件,我成了整个公司代码写得最规范的码农
java·后端
Danny_FD12 小时前
React中可有可无的优化-对象类型的使用
前端·javascript
星星电灯猴12 小时前
Charles抓包工具深度解析:如何高效调试HTTPHTTPS请求与API接口
后端
isfox13 小时前
Hadoop 版本进化论:从 1.0 到 2.0,架构革命全解析
大数据·后端
LeeAt13 小时前
从Promise到async/await的逻辑演进
前端·javascript
normaling13 小时前
四、go语言指针
后端
前端Hardy13 小时前
HTML&CSS:3D 轮播图全攻略
前端·javascript
前端Hardy13 小时前
7 个技巧助你写出优雅高效的 JavaScript 异步代码
前端·javascript·面试
yeyong13 小时前
用springboot开发一个snmp采集程序,并最终生成拓扑图 (二)
后端