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

除了上篇介绍的二分插入排序,还有这次介绍的希尔排序(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,12,5,4,94,63,23,75,22,43,27,46],以n/2为增量,那么整个排序流程就是这样的:

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

代码

package main

import (
    "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改成step
func 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]
        }
    }
}

运行结果

原文地址:http://blog.51cto.com/13022101/2151304

时间: 2024-11-13 08:08:50

[golang] 数据结构-希尔排序的相关文章

数据结构 - 希尔排序(Shell&amp;#39;s Sort) 具体解释 及 代码(C++)

数据结构 - 希尔排序(Shell's Sort) 具体解释 及 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24363981 希尔排序(Shell's Sort), 又称"缩小增量排序"(Diminishing Increment Sort), 是插入排序的一种. 主要思想是: 先将整个记录, 通过间隔分成若干个子序列, 分别进行插入排序, 待整个序列基本有序时, 再进行一次插入排序. 由于插入排

[数据结构]希尔排序

一.问题描述 内部排序是一件具有重大意义的问题,许多项目的实现中都需要用到排序. 我们知道,排序的算法有许多种,每种排序算法的时间复杂度和空间复杂度不尽相同.在解决实际问题时,往往需要根据实际需要选择排序算法. 本实验重点介绍希尔排序的算法实现及其原理,简要说明与其相关的直接排序算法,并讨论希尔排序中步长的选择对排序速度的影响. 二.数据结构——顺序结构 本实验重点在算法实现上,数据结构的思想被弱化了.在排序过程中,由于维护序关系的需要,要有交换的操作,这就破坏了ADT的物理位置的相邻反映逻辑的

[golang] 数据结构-地精排序

碎碎念这是一个名字起得很随便的排序算法,是我我就叫他史莱姆排序ㄟ(▔,▔)ㄏ 原理地精排序是也是一种交换排序.它只进行一轮比较,在这轮比较中,遇到比较前面元素大就向后移动一位继续比较,遇到比前面值小就和前面的值交换,并向前移动一位. 复杂度对已经排序号的队列哥布林只需从头走到尾就结束了,所以最好情况时间复杂度就是O(n),平均的时间复杂度也和冒泡排序一样也是O(n^2). 代码 package main import ( "time" "fmt" "mat

[golang] 数据结构-鸡尾酒排序

吐个槽又是一个不正经取名的排序算法.真要说和鸡尾酒间的关系,大概就是想喝到鸡尾酒(得到排序好的队列)就要摇晃酒杯让不同的成分混合均匀(向两个方向冒泡排序) 原理鸡尾酒排序(Cocktail Sort)是冒泡排序的一种优化算法.原本的冒泡排序只能在一轮中挑出一个值移动到最后,而鸡尾酒则可以在一轮里挑最大的移到最后,再挑最小的移到最前面.实际上就是先正向进行一轮普通的冒泡排序,然后再逆向进行一轮反向冒泡,每轮冒泡都缩小一点范围. 复杂度最好情况是正序排列的数列O(n),最坏情况是逆序O(n^2),平

数据结构精要------直接插入排序和希尔排序算法

上篇总结中主要实践了算法的内排序的选择排序,那么接下来我们继续实践插入排序排序的两种:直接插入排序和希尔排序算法. -----直接插入排序 package com.sort; /** * 直接插入排序 * * @author weixing-yang * * 算法思路: * 每步将一个待排序的元素,插入到前面已排序好的一组元素中的适当位置, * 直到所有元素全部出入完成为止. */ public class InsertionSort { public void insertionSort(in

数据结构例程——插入排序之希尔排序

本文是[数据结构基础系列(9):排序]中第3课时[插入排序之希尔排序]的例程. 1.希尔排序 #include <stdio.h> #define MaxSize 20 typedef int KeyType; //定义关键字类型 typedef char InfoType[10]; typedef struct //记录类型 { KeyType key; //关键字项 InfoType data; //其他数据项,类型为InfoType } RecType; //排序的记录类型定义 void

SDUT 3403 数据结构实验之排序六:希尔排序

数据结构实验之排序六:希尔排序 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 我们已经学习了各种排序方法,知道在不同的情况下要选择不同的排序算法,以期达到最好的排序效率:对于待排序数据来说,若数据基本有序且记录较少时, 直接插入排序的效率是非常好的,希尔排序就是针对一组基本有序的少量数据记录进行排序的高效算法.你的任务是对于给定的数据进行希尔排序,其中增量dk=n/(2^k)(k=1,2

13. 蛤蟆的数据结构进阶十三排序实现之希尔排序法

13. 蛤蟆的数据结构进阶十三排序实现之希尔排序法 本篇名言:"一个人光溜溜的到这个世界来 ,最后光溜溜的离开这个世界而去 , 彻底想起来 , 名利都是身外物 ,只有尽一人的心力 , 使社会上的人多得他工作的裨益 ,是人生最愉快的事情.--邹韬奋" 下面是希尔排序法了. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47706135 1.  希尔排序 希尔排序(ShellSort)是插入排序的一种.也称缩小增量排序

【数据结构与算法】希尔排序

希尔排序的时间复杂度是O(n^1.3)~O(n^2),空间复杂度是O(1). 代码如下: /** * 源码名称: ShellSort.java * 日期:2014-08-11 * 程序功能:希尔排序 * 版权:[email protected] * 作者:A2BGeek */ public class ShellSort { public void shellSort(int[] in) { int length = in.length; int span = length / 2; int i