[golang] 数据结构-希尔排序

[golang] 数据结构-希尔排序,第1张

概述除了上篇介绍的 二分插入排序,还有这次介绍的希尔排序(Shell‘s Sort),也是对直接插入排序算法的优化。 原理 希尔排序,就是按某个增量值对数据进行分组,每组单独排序好后,再缩小这个增量,然后按新增量对数据分组后每个分组再各自排序。最终增加缩小到1的时候,排序结束。所以希尔排序又叫缩小增量排序(Diminishing Increment Sort) 关于增量 最佳增量值的选择其实是个数学难 除了上篇介绍的 二分插入排序,还有这次介绍的希尔排序(Shell‘s Sort),也是对直接插入排序算法的优化。

原理
希尔排序,就是按某个增量值对数据进行分组,每组单独排序好后,再缩小这个增量,然后按新增量对数据分组后每个分组再各自排序。最终增加缩小到1的时候,排序结束。所以希尔排序又叫缩小增量排序(Diminishing Increment Sort)

关于增量
最佳增量值的选择其实是个数学难题,有兴趣的可以自己搜下相关资料。
常用的增量有 n/2(这个又叫希尔增量)、n/3、2^k-1(hibbard增量)等,实际使用中稍微改版增量也可能使排序的性能产生很大的波动。
比如使用n/2的增量,就是初始增量就是 length/2,第二轮分组时就再除2:length/4,直至增量值变成1

流程
假设有个数组:[8,12,6,33,5,4,94,63,23,75,22,43,27,46],以n/2为增量,那么整个排序流程就是这样的:

复杂度
不同增量复杂度不同。n/2时平均的时间复杂度为O(n^2)。
相较直接插入排序,希尔排序减少了比较和交换的次数,在中小规模的排序中,性能表现较好。但随着数据量增大,希尔排序与其他更好的排序算法(快排、堆排、并归等)仍有较大差距。

代码

package mainimport (    "fmt"    "time"    "math/rand")func main() {    var length = 15    var List []int    // 以时间戳为种子生成随机数,保证每次运行数据不重复    r := rand.New(rand.NewSource(time.Now().UnixNano()))    for i := 0; i < length; i++ {        List = append(List,int(r.Intn(1000)))    }    fmt.Println(List)    // 这里就以n/2为增量z    gap := 2    step := length / gap    for step >= 1 {        // 这里按步长开始每个分组的排序        for i := step; i < length; i++ {            // 将按步长分组的子队列用直接插入排序算法进行排序            insertionSortByStep(List,step)        }        // 完成一轮后再次缩小增量        step /= gap        // 输出每轮缩小增量各组排序后的结果        fmt.Println(List)    }}// 这里把上篇直接选择排序的算法抽出来,并将步长从1改成stepfunc insertionSortByStep(tree []int,step int) {    for i := step; i < len(tree); i++ {        for j := i; j >= step && tree[j] < tree[j-step]; j -= step {            tree[j],tree[j-step] = tree[j-step],tree[j]        }    }}

运行结果

总结

以上是内存溢出为你收集整理的[golang] 数据结构-希尔排序全部内容,希望文章能够帮你解决[golang] 数据结构-希尔排序所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1270408.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存