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

结果比较

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

总结

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

相关推荐
panxianren4 小时前
Bun 1.4 的 bun test --parallel 将 4 秒的测试套件缩短到约 1 秒
java·javascript
码事漫谈5 小时前
骂AI,会让它做得更好吗?
后端
陈随易6 小时前
bm2,Node.js 与 Bun 项目部署新选择
前端·后端·程序员
架构技术专栏7 小时前
AI Agent 框架怎么选:从一次制度查询拆出技术边界
后端·面试
可乐鸡翅yeah_7 小时前
FFmpeg 生成 HLS 独立分片 independent‑segments 参数到底有什么用
javascript·ffmpeg·音视频·safari·m3u8
福兮说7 小时前
canvas 旋转图片的六个坑:四角被裁、Math.ceil 多出 1px 黑边、JPG 角发黑、翻转方向反了
前端·javascript·图像处理·canvas
Ai-_Man9 小时前
您您这可以把Grok的多个会话比如说。左侧的多个会话一次性导出吗?不是单条会话里面的多次会对话。AI导出鸭
javascript·人工智能·ai·小程序·电脑
明月_清风9 小时前
SaaS 的三层挣钱逻辑,正在被 AI 从第一层击穿
人工智能·后端
liangshanbo12159 小时前
JavaScript 异步核心主线
javascript·事件循环·异步操作
传人once10 小时前
悬停旋转放大和位移效果如何写
javascript·css·动画