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