冒泡排序算法优化:成数十倍提高的算法效率

今天哈士奇的算法分享又来了,这篇文章的主题是优化冒泡排序算法。从哈士奇之前的文章大家可以知道,冒泡排序算法是一种稳定且十分简单的排序算法。但是它的缺点也十分明显,效率低,以及不太适用于基本有序的数组。大家可以复习一下前面的文章# 排序算法有多少种?史上最全排序算法在这里!! 那么如何提高冒泡排序算法的效率呢?今天哈士奇来给大家分享冒泡排序算法plus!!

传统的冒泡排序算法

js 复制代码
function swap(arr,a,b) {
    let temp = arr[a];
    arr[a] = arr[b];
    arr[b] = temp;    
}

function bubbleSort(arr) {
    for(let m = 0;m<arr.length;m++){
        for(let n=0;n<arr.length-1-m;n++){
            if(arr[n]>arr[n+1]){
                swap(arr,n,n+1)
                
            }
            console.log('第'+m+'次排序后的数组为:'+arr)
        }
    }
    return arr;
}

第一次优化:适用于基本有序的数组

如果冒泡排序在某一次排序的过程中就已经将数组排成所需要的队列,那么在后续的循环中就不需要再次进行查找了,即在此次排序就终止冒泡排序的查找,我们将节约中途排序成功后的所有时间和资源消耗。因此需要在算法中设置一个检测变量,当某一次内循环没有任何变化的时候,我们就可以知道排序已经结束了。所以就有了以下代码

js 复制代码
function bubbleSort(arr) {
    for(let m = 0;m<arr.length;m++){
        let flag = false;
        for(let n=0;n<arr.length-1-m;n++){
            if(arr[n]>arr[n+1]){
                swap(arr,n,n+1);
                flag = true;
            }
        }
        if(!flag){
            break;
        }
    }
    return arr;
}

function swap(arr,a,b) {
    let temp = arr[a];
    arr[a] = arr[b];
    arr[b] = temp;    
}

在上面的优化代码中,添加了一个检测变量flag,默认为false,进行内循环只要发生了交换,就改为true,代码即刻停止查找。在下面的实例中只需要七次排序就结束了。节约了第八次的时间和花费。

第二次优化:节约最后一个元素的开销

冒泡排序算法的特点在于每次冒泡的最后一个都是当前循环中最大的数,简单的来说,如果我们在冒泡中出现了一次冒泡排到两个正确位置,那么在后面的排序中就可以跳过这次冒泡的次序,减少交换的次数。大家可以参照以下代码

js 复制代码
function bubbleSort(arr){
    let len=arr.length,k=len-1,swapPos=0;
    for(let m=0;n<len;n++){
        let flag=false;
        for(n=0;n<k;n++){
            if(arr[n]>arr[n+1]){
                swap(arr,n,n+1);
                flag=true;
                swapPos=n;
            }
        }
        if(!flag){
            break;
        }
        k=swapPos;
    }
}
function swap(arr,a,b){
    let temp=arr[a];
    arr[a]=arr[b];
    arr[b]=temp;
}

在第三次和第四次排序数组之间,从五次排序直接跳到了三次排序,减少了中间的四次排序查找的过程,再次减少了资源和时间的消耗,至此,在冒泡排序算法上面我们基本已经优化到了极限。

测试

接下来我们来测试一下这些代码的运行时间

js 复制代码
function bubbleSort1(arr) {
    for(let m = 0;m<arr.length;m++){
        for(let n=0;n<arr.length-1-m;n++){
            if(arr[n]>arr[n+1]){
                swap(arr,n,n+1)
                
            }
        }
    }
    return arr;
}
function bubbleSort2(arr) {
    for(let m = 0;m<arr.length;m++){
        let flag = false;
        for(let n=0;n<arr.length-1-m;n++){
            if(arr[n]>arr[n+1]){
                swap(arr,n,n+1);
                flag = true;
            }
        }
        if(!flag){
            break;
        }
    }
    return arr;
}
function bubbleSort3(arr){
    let len=arr.length,k=len-1,swapPos=0;
    for(let m=0;m<len;m++){
        let flag=false;
        for(n=0;n<k;n++){
            if(arr[n]>arr[n+1]){
                swap(arr,n,n+1);
                flag=true;
                swapPos=n;
            }
        }
        if(!flag){
            break;
        }
        k=swapPos;
    }
}
function swap(arr,a,b){
    let temp=arr[a];
    arr[a]=arr[b];
    arr[b]=temp;
}   
function shuffle(a){
    let len=a.length;
    for(let i=0;i<len;i++){
        let index=Math.floor(Math.random()*len-i);
        let temp=a[index];
        a[index]=a[len-1-i];
        a[len-1-i]=temp;
    }
}
function test(fn){
    let array=[]
    for(let i=0;i<10000;i++){
        if(i<=1000)
        array[i]=1000-i;
        else
        array[i]=i;
    }
    console.log('========================')
let start = new Date-0
fn(array);
console.log('部分有序的数组排序时间:'+fn.name+' '+(new Date-start)+'ms')
shuffle(array);
start = new Date-0
fn(array)
console.log('完全无序的数组排序时间:'+fn.name+' ' +(new Date-start)+'ms')

}

test(bubbleSort1)
test(bubbleSort2)  
test(bubbleSort3)

根据上述结果我们可以看出来,在第二次优化以后,冒泡排序的效率相比以前提高了十多倍甚至在乱序情况下提高了上百倍,至此,最终优化的冒泡排序算法新鲜出炉,大家快用用看吧!!!

春招加油

假如您也和我一样,在准备春招。欢迎加我微信 shunwuyu ,这里有几十位一心去大厂的友友可以相互鼓励,分享信息,模拟面试,共读源码,齐刷算法,手撕面经。来吧,友友们!

相关推荐
mit6.8245 分钟前
[Cyclone] 哈希算法 | SIMD优化哈希计算 | 大数运算 (Int类)
算法·哈希算法
c++bug8 分钟前
动态规划VS记忆化搜索(2)
算法·动态规划
哪 吒10 分钟前
2025B卷 - 华为OD机试七日集训第5期 - 按算法分类,由易到难,循序渐进,玩转OD(Python/JS/C/C++)
python·算法·华为od·华为od机试·2025b卷
gnip36 分钟前
总结一期正则表达式
javascript·正则表达式
军训猫猫头1 小时前
1.如何对多个控件进行高效的绑定 C#例子 WPF例子
开发语言·算法·c#·.net
爱分享的程序员1 小时前
前端面试专栏-算法篇:18. 查找算法(二分查找、哈希查找)
前端·javascript·node.js
翻滚吧键盘1 小时前
vue 条件渲染(v-if v-else-if v-else v-show)
前端·javascript·vue.js
你这个年龄怎么睡得着的1 小时前
为什么 JavaScript 中 'str' 不是对象,却能调用方法?
前端·javascript·面试
success1 小时前
【爆刷力扣-数组】二分查找 及 衍生题型
算法
南屿im1 小时前
JavaScript 手写实现防抖与节流:优化高频事件处理的利器
前端·javascript