算法学习in js:希尔排序

553 阅读2分钟

前言

希尔排序是一种基于插入排序的排序算法,经过改动,它解决了插入排序所存在的问题:对于大规模乱序数组插入排序会很慢,因为它只能交换相邻的元素。假设数组最小元素在末尾,升序排序中它就需要移动N-1次到数组开头。而希尔排序通过交换不相邻的元素对数组进行局部排序,最终用插入排序将局部有序数组进行最后排序

思想及图解

希尔排序的思想是使数组中任意间隔为h的元素都是有序的。这样的数组被称为h有序数组。 ——《算法(第4版)》

如下图所示

如此,数组中的元素即可完成较大跨度的排序。

随着排序的进行,h不断减小,子数组的规模在不断增大,有序性不断提升,当h = 1时即相当于插入排序。此时整体数组已呈局部有序,此时对于插入排序而言效率非常之高。

代码实现

  sort(array) {
    const N = array.length;
    let h = 1;
    while(h < N/3){ //设置h
      h = 3 * h + 1;
    }
    while(h >= 1){
      //使数组变为h有序
      for(let i = h; i < N; i++){
        //将array[i]插入到array[i-h],array[i- 2*h],array[i - 3*h]
        for(let j = i; j >= h && this.less(array[j], array[j-h]); j -= h){
          this.exch(array, j, j-h);
        }
      }
      h = Math.floor(h / 3);
    }
  }

CodePen打开

如此便可通过h进行局部性的排序。

总结

由于h选择的原因,希尔排序目前的性能还没有被完全研究透彻,即使是如上代码对h的选择也是。

而在实际应用中,希尔排序适合中等大小的数组,它的代码量小,较为简单,同时不占同额外的空间。但是对于规模很大的数组,希尔排序的表现可能就没那没好了,不及有如快排等的算法。工程实践中,比如工程初始阶段可以使用希尔排序,而后续阶段再考虑是否使用更复杂的排序算法。

参考资料

《算法(第4版)》