前言
这几天正在研习数据结构与算法,在掘金社区找到一篇《JS家的排序算法》,里面讲的是十大排序算法,以图文的形式生动展现了各种算法是如何演算的。
当我看到冒泡排序算法,选择排序算法时总结了一下这两种算法的窍门:
冒泡排序算法:循环第一遍,找出最大值,并将其放到数组最后;循环第二遍,找出第二大值,并将其放入到数组倒数第二的位置;.......;一直循环,直到将这个数组排序好。
选择排序算法:循环第一遍,找出最小值,并将其放到数组开头;循环第二遍,找出第二小值,并将其放入到数组第二个位置;......;一直循环下去,直到将这个数组排序好。
在某个清晨醒来,我突然来了一个idea,既然在一次循环中只找最大值,或者只找最小值,最后得出排序,为什么不能在一次遍历中,即找到最小值同时又找到最大值呢,这样一来,循环一次,我们能够找出两个值出来,那么对于一个100个元素的数组,我们只需要循环50次,即可将整个数组排序完成,那这样有可能会提高排序效率呀,但我转念一想,这个想法如此简单,应该会有对应的算法吧,但是去百度了一下,貌似没有找到,所以我带着这个想法,我撸起了代码......
动手
因为一次循环,即寻找最大值,又寻找最小值,所以我为这个算法取了一个好记的名字:双规排序算法,在鼓捣了半个小时后,终于出来了,话不多说,直接上菜:
function doublegauge(arr){
let length = arr.length
let temp
for(let i=0;i<length/2;i++){
// 每次循环,在一开始的时候,我们假设数组的两端是最小值,和最大值
// 如果 最小值>最大值,则进行交换,交换完成后,我们能够确定,这两端是已经排序好了,为进入内部循环打下了基础。
if(arr[i]>arr[length-1-i]){
temp = arr[i]
arr[i] = arr[length-1-i]
arr[length-1-i] = temp
}
// 进入内部循环,如果arr[j]小于最小值,则将首部和arr[j]进行交换,保证最前的元素为最小值
// 如果arr[j]大于最大值,则将尾部和arr[j]进行交换,保证最后的元素为最大值
for(let j=i;j<length-i;j++){
if(arr[j]<arr[i]){
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}else if(arr[j]>arr[length-1-i]){
temp = arr[length-1-i]
arr[length-1-i]=arr[j]
arr[j]=temp
}
}
}
return arr
}
优势
这个算法虽然思路和冒泡算法和排序算法差不多,但是从执行次数来看,此算法执行次数会比其他两种少很多,比如:一个100个元素的数组
冒泡算法执行次数:100+99+98+...+1
排序算法执行次数:100+99+98+...+1
双规算法执行次数:100+98+96+...+2
劣势
相对于冒泡排序算法和选择排序算法,此种算法的劣势在于在每次的内部循环中可能出现2次比较。
最后
因为我是一个半路出家的前端JSer,所以不知道这个算法是否正确,也不知道这种算法是否已经存在,但是我还是在这里记录一下。我试了一些数组,都能够做到排序,也不知道有没有什么漏洞。更重要的是,如果这个算法是正确的,那么相较于其他算法,此算法性能如何呢?虽然我前面说了,从直觉上面来看,确实会比冒泡算法和排序算法效率高,但我并没有动手验证,如果哪个大神看到这篇文章,请多多指教,非常感谢啦~,撒花~