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

今天哈士奇的算法分享又来了,这篇文章的主题是优化冒泡排序算法。从哈士奇之前的文章大家可以知道,冒泡排序算法是一种稳定且十分简单的排序算法。但是它的缺点也十分明显,效率低,以及不太适用于基本有序的数组。大家可以复习一下前面的文章# 排序算法有多少种?史上最全排序算法在这里!! 那么如何提高冒泡排序算法的效率呢?今天哈士奇来给大家分享冒泡排序算法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 ,这里有几十位一心去大厂的友友可以相互鼓励,分享信息,模拟面试,共读源码,齐刷算法,手撕面经。来吧,友友们!

相关推荐
Dread_lxy9 分钟前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
ChoSeitaku13 分钟前
链表循环及差集相关算法题|判断循环双链表是否对称|两循环单链表合并成循环链表|使双向循环链表有序|单循环链表改双向循环链表|两链表的差集(C)
c语言·算法·链表
Fuxiao___21 分钟前
不使用递归的决策树生成算法
算法
我爱工作&工作love我26 分钟前
1435:【例题3】曲线 一本通 代替三分
c++·算法
用户3157476081351 小时前
成为程序员的必经之路” Git “,你学会了吗?
面试·github·全栈
白-胖-子1 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级
workflower1 小时前
数据结构练习题和答案
数据结构·算法·链表·线性回归
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
好睡凯1 小时前
c++写一个死锁并且自己解锁
开发语言·c++·算法
Sunyanhui11 小时前
力扣 二叉树的直径-543
算法·leetcode·职场和发展