双规排序算法

204 阅读3分钟

前言

这几天正在研习数据结构与算法,在掘金社区找到一篇《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,所以不知道这个算法是否正确,也不知道这种算法是否已经存在,但是我还是在这里记录一下。我试了一些数组,都能够做到排序,也不知道有没有什么漏洞。更重要的是,如果这个算法是正确的,那么相较于其他算法,此算法性能如何呢?虽然我前面说了,从直觉上面来看,确实会比冒泡算法和排序算法效率高,但我并没有动手验证,如果哪个大神看到这篇文章,请多多指教,非常感谢啦~,撒花~