希尔算法的简介
希尔算法是插入算法的升级版,D.L.Shell 于 1959提出,是一种减少增量算法,提出的过程为作者发现插入算法的时间复杂度会随着数组的有序性上升而下降,所以采用分组的算法,使各个组内变得有序,提升整体的有序性,从而减少插入算法的时间.
希尔算法的原理
比如说
我们现在有一组数据
(这里截多一点是防止水印把数据挡住)
我们想将其变得有序
但是我们是笨笨星人
每一次只能对一组数据进行比较
我们该怎么将其变得有序呢
如果我们将其将相邻的数字两两比较
并重复10次
一定就可以得到想要的结果
但是这需要90次时间太长了
所以,聪明的你想出来一种新办法
增加比较数字的间隔
然后将间隔的大小除以3
再进行比较,直到间隔为一,结束比较
比如说
我们将间隔设为9
即31和3进行比较,而31大于3
所以交换位置
然后就无法进行比较了
因为9后面就没有数据了
这时候我们就可以调整间隔
使间隔为原来的1/3
再从头开始比较
即9和26进行敝教
因为9<26
所以不用交换
在对9的后一位进行相同的操作
即45和4213进行比较
直到间隔为1,再比较完后结束
这个就是大名鼎鼎的希尔算法的原理
希尔算法的实现
如图,便是对希尔算法的简单实现
上图是运行结果( 最后两个数字分别为数字交换次数和数字比较次数)
希尔算法的注意事项
1 希尔算法并不稳定,是存在无法正确排序的情况的
当我把增量变为3时
输出的结果并不是我们所想要的
一开始,我还以为是我的逻辑写错了
但我加断点挨个调试的时候发现
我的程序时完全按照希尔算法运行的
所以
只能是这个算法本身有问题
我举一个例子
比如,一串数据在增量为1的时候前三个数据为
3 2 1
我们先对3和2比较并交换
在对3和1比较并交换
然后当程序结束时前两位数据却为2 1
这就造成了上述数据的结果
我的优化方案(对于我的程序)
将死循环跳出的条件修改在里面在增加一层判断
这里增加一个全局变量w并将最外层循环的跳出条件改为w!=1
我的思路是将add=1时不跳出,而是对数据进行检查
如果并不是完全有序
就不跳出
再进行一次排序
直到完全有序时在跳出
在增量为3时
我们可以得到如上结果
进行21次交换和61次比较
尽管相比原来交换次数和比较增加
但是输出的结果更精准
但是原来的最笨的方法比较次数却增加了
所以
再优化
通过将增量的重置来减少比较
如图,我们不仅获得了正确的排序,还减少了比较的次数
2希尔算法在增量的减少方式上没有公认的最优解
希尔自己的建议是减半,然而有人认为除以三再加以是更好的解决方案
事实是,在某些情况下,减半更好
但在某些情况下
除以三却更快
直至今日
并没有一个定论
标签:间隔,交换,算法,笔记,希尔,增量,比较 From: https://blog.csdn.net/AD057708281024/article/details/139247168