参考书:
严蔚敏-数据结构
希尔排序(Shell's Sort)
希尔排序又称"缩小增量排序",归属于插入排序一类,简单来说,和我们的插入排序比,它更快.
奇妙的记忆点:
内排序(内存排序就够了)
不稳定(排序后原始顺序无法保证)
希尔排序重点在于分割.
基本思想:
将整个待排序记录序列分割为若干个子序列,然后对每一个子序列进行直接插入排序.
直接插入排序:
不得不先讲一下直接插入排序了,毕竟希尔排序要使用到直接插入排序.
直接插入算法重点在于分区,有序区与无序区.假设我们有一个数组arr
for(var i = 1;i<arr.length;i++){
var key = arr[i];
var j = i;
while(j>0&&arr[j-1]>key){
arr[j] = arr[j-1];
j--;
}
arr[j]=key;
}
其中i=1
,i
~arr
.len-1
为我们的无序区,而i=0
为我们的有序区.temp
用于记录无序区准备进入有序区的元素,j
用于从右往左遍历有序区并将元素往后推,找出相应的插入位置,将temp
插入对应位置.
希尔排序:代码
希尔排序关键在于增量的设置,根据增量分割数组并逐步进行直接插入排序,增量逐趟减少,并最后使得整个数组基本有序,再对整体进行直接插入排序.
记忆点
best condition: T(n) = O(n*log2 n)
baddest condition: T(n) = O(n*log2 n)
average condition: T(n) = O(n*log n)
基本的思路就是根据增量分割数组,如var arr = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
我们增量为5,则分割为
[3,15,46]
[44,36,4]
[38,26,19]
[5,27,50]
[47,2,48]
并对每一组进行直接插入排序
再把增量变为2(减半),再进行分割,直到增量为1,再对全体进行一次直接插入排序就可以了.
简略的代码如下:
var len =arr.length;
gap = Math.floor(len/2);
while(gap!==0){
for(var i = gap;i<len;i++){
var temp = arr[i];
var j;
for(j=i-gap;j>=0&&temp<arr[j];j-=gap){
arr[j+gap] = arr[j];
}
arr[j+gap] = temp;
}
gap=Math.floor(gap/2);
}
return arr;
简单说一下,i从gap位开始,那么每组的有序区已经确定了一位,接下来将i-gap位的数根据组的不同插入有序区,就完成了每组的直接插入排序了.
相关流程图
动态定义间隔序列
这是我在掘金看来的
希尔排序的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列。动态定义间隔序列的算法是《算法(第4版》的合著者Robert Sedgewick提出的。
while(gap < len/5) { //动态定义间隔序列
gap =gap*5+1;
}
参考来源:http://gold.xitu.io/post/57dc...
详细介绍了十种算法,大家可以去学习下.
以后大概会尽量每天更新一个算法学习吧,温故而知新
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。