Fork me on GitHub

排序算法-希尔排序

希尔排序(Shell Sort)的基础

希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:

  1. 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
  2. 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。

实现希尔排序(n为待排序arr.length)

实现理论

先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量 =1( < …<d2<d1),即所有记录放在同一组中进行直接插入排序为止。

该方法实质上是一种分组插入方法

比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。
一般的初次取序列的一半为增量,以后每次减半,直到增量为1。

实现思路

假设待排序文件有10个记录,其关键字分别是:
592,401,874,141,348,72,911,887,820,283。
增量序列的取值依次为:n = 10, 则增量d1 = 10/2 = 5。
5,2,1
计算过程
算法时间复杂度:T(n) = O(n*logn^2)
内排序(内存排序就够了)
不稳定(排序后原始顺序无法保证)

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function shellSort(array) {
let arr = array.slice(),
len = arr.length;
for(var fraction = Math.floor(len/2); fraction > 0; fraction = Math.floor(fraction/2)){
// 这里实质上有进行了直接插入排序
for(var i = fraction; i < len; i++){
for(var j = i - fraction; j >= 0 && arr[j] > arr[fraction + j]; j -= fraction){
var temp = arr[j];
arr[j] = arr[fraction + j];
arr[fraction + j] = temp;
}
}
}
return arr;
}

var arr1 = [592,401,874,141,348,72,911,887,820,283];
let arr2 = shellSort(arr1);
console.log(arr1); // [592, 401, 874, 141, 348, 72, 911, 887, 820, 283]
console.log(arr2); // [72, 141, 283, 348, 401, 592, 820, 874, 887, 911]

PS:首个增量一般取值为 Math.floor(arr.length/2),对每个分组进行直接插入排序。
重复上面过程,知道增量为1时,整个数组恰被分成一组,算法便终止。

参考文档:
十大经典排序算法
基本算法学习(一)之希尔排序(JS)
希尔排序

-------------本文结束感谢您的阅读,如果本文对你有帮助就记得给个star-------------
Donate comment here