跟着动画学 Go 数据结构之希尔排序

简介: 在插入排序中,在待排序序列的记录个数比较少,而且基本有序,则排序的效率较高。1959 年,Donald Shell 从“减少记录个数” 和 “基本有序” 两个方面对直接插入排序进行了改进,提出了希尔排序算法。

希尔排序

在插入排序中,在待排序序列的记录个数比较少,而且基本有序,则排序的效率较高。

1959 年,Donald Shell 从“减少记录个数” 和 “基本有序” 两个方面对直接插入排序进行了改进,提出了希尔排序算法。

希尔排序又称为“缩小增量排序”。即将待排序记录按下标的一定增量分组(减少记录个数),对每组记录使用直接插入排序算法排序(达到基本有序);随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1,整个序列基本有序,再对全部记录进行一次直接插入排序。


算法思想

Shell 排序是一种高效的排序算法,基于插入排序算法。这种算法避免了插入排序中的大量移动,如果较小的值在最右边,就必须移到最左边。较小的值在最右边,必须移到最左边。


算法步骤:

  1. 设待排序的记录存储在数组 array[1...n]  中,增量序列为 {g1, g2, ..., gt} , n>g1>g2>...>gt=1
  2. 第一趟增量 g1, 所有间隔为 g1 的记录分在一组,对每组记录进行插入排序。
  3. 第二趟取增量 g2,所有间隔为 g2 的记录分在一组,对每组记录进行插入排序。
  4. 依次进行下去,直到所取增量 gt = 1,所有记录在一组中进行插入排序。

图解算法

假设我们有一个数组: [7, 4, 3, 5, 2, 1, 6] :

第一次希尔排序间隔为 3 时:

image.png

第二次希尔排序间隔为 2 时:

image.png

第三次希尔排序间隔为 1 时:

image.png

Go 代码实现:

package main
import "fmt"
func swap(array []int, a int, b int) {
    array[a] = array[a] + array[b]
    array[b] = array[a] - array[b]
    array[a] = array[a] - array[b]
}
func shellSort(array []int, length int) {
    for gap := length / 2; gap > 0; gap = gap / 2 {
        for i := gap; i < length; i++ {
            var j = i
            for {
                if j-gap < 0 || array[j] >= array[j-gap] {
                    break
                }
                swap(array, j, j-gap)
                j = j - gap
            }
        }
    }
}
func main() {
    nums := []int{7, 4, 3, 5, 2, 1, 6}
    length := len(nums)
    shellSort(nums, length)
    for i := 0; i < length; i++ {
        fmt.Println(nums[i])
    }
}


运行结果:

[Running] go run "e:\Coding Workspaces\LearningGoTheEasiestWay\Go 数据结构\希尔排序\main.go"
1
2
3
4
5
6
7

总结

时间复杂度:希尔排序的时间复杂度和增量序列有关,不同的增量序列其时间复杂度不同。当n 处于某个特定的范围内,希尔排序的时间复杂度为 O(n1.3),希尔排序复杂度的下界是 O(nlogn),最坏情况下的时间复杂度为 O(n2),但是,希尔排序还是没有快速排序快。

空间复杂度:希尔排序在分组进行插入排序时使用了一个辅助空间 j,空间复杂度为 O(1)

稳定性:希尔排序的分组导致不同组间的相同数字可能会调换位置,所以希尔排序是不稳定的排序算法。

相关文章
|
2月前
|
Go 索引
掌握Go语言:Go语言范围,优雅遍历数据结构,简化代码操作实战解析(24)
掌握Go语言:Go语言范围,优雅遍历数据结构,简化代码操作实战解析(24)
|
2月前
|
Go
《Go 简易速速上手小册》第3章:数据结构(2024 最新版)(下)
《Go 简易速速上手小册》第3章:数据结构(2024 最新版)(下)
16 1
|
2月前
|
存储 供应链 数据可视化
《Go 简易速速上手小册》第3章:数据结构(2024 最新版)(上)
《Go 简易速速上手小册》第3章:数据结构(2024 最新版)(上)
54 1
|
17天前
|
算法 搜索推荐
数据结构算法--6 希尔排序和计数排序
**希尔排序**是插入排序的改进版,通过分组插入来提高效率。它逐步减少元素间的间隔(增量序列),每次对每个间隔内的元素进行插入排序,最终增量为1时进行最后一次直接插入排序,实现整体接近有序到完全有序的过程。例如,对数组`5, 7, 4, 6, 3, 1, 2, 9, 8`,先以间隔`d=4`排序,然后`d=2`,最后`d=1`,完成排序。计数排序则适用于0到100的数值,通过统计每个数出现次数,创建对应计数数组,再根据计数重建有序数组,时间复杂度为`O(n)`。
|
19天前
|
存储 安全 Java
Go语言入门之路——数据结构
Go语言入门之路——数据结构
|
2月前
|
存储 搜索推荐 算法
[数据结构]————排序总结——插入排序(直接排序和希尔排序)—选择排序(选择排序和堆排序)-交换排序(冒泡排序和快速排序)—归并排序(归并排序)
[数据结构]————排序总结——插入排序(直接排序和希尔排序)—选择排序(选择排序和堆排序)-交换排序(冒泡排序和快速排序)—归并排序(归并排序)
|
1月前
|
算法 Shell C语言
数据结构与算法——希尔排序(引例、希尔增量序列、原始希尔排序、代码、时间复杂度、Hibbard增量序列、Sedgewick增量序列)
数据结构与算法——希尔排序(引例、希尔增量序列、原始希尔排序、代码、时间复杂度、Hibbard增量序列、Sedgewick增量序列)
16 0
|
1月前
|
存储 搜索推荐
深入了解数据结构第四弹——排序(1)——插入排序和希尔排序
深入了解数据结构第四弹——排序(1)——插入排序和希尔排序
16 0
|
2月前
|
C语言
【C语言/数据结构】排序(直接插入排序|希尔排序)
【C语言/数据结构】排序(直接插入排序|希尔排序)
20 4
|
2月前
|
搜索推荐 算法 Shell
【数据结构与算法】直接插入排序和希尔排序
【数据结构与算法】直接插入排序和希尔排序