希尔排序详解


1️⃣ 希尔排序(Shell Sort)简介

希尔排序是 插入排序的一种改进 ,它由 Donald Shell 于 1959 年提出,也叫 缩小增量排序

核心思想:

  • 插入排序在数据量大或者序列几乎倒序时效率低,因为每次只能移动相邻元素。
  • 希尔排序通过设置一个 "间隔 gap",把序列分成若干子序列,然后对每个子序列进行插入排序。
  • 随着排序进行,gap逐渐减小,最后当 gap = 1 时,整个数组已经接近有序,这时做最后一轮插入排序效率很高。

简单步骤:

  1. 选择一个增量序列 gap(初始通常是 n/2)。
  2. 按 gap 把数组划分成若干个子序列。
  3. 对每个子序列进行插入排序。
  4. 缩小 gap(通常 gap = gap / 2),重复步骤 2~3。
  5. 直到 gap = 1,做最后一次插入排序。

示意(此处只是举例方便,gap为3):

假设数组 [8, 5, 3, 7, 6, 2, 4, 1],gap = 3,序列分组:

  • 第1组:8, 7, 4
  • 第2组:5, 6, 1
  • 第3组:3, 2

每组内部插入排序,然后再减 gap,最后 gap = 1 时做整体插入排序。


2️⃣ 插入排序(Insertion Sort)简介

核心思想:

  • 每次从未排序的部分取一个元素,插入到已排序部分的合适位置。
  • 适合数据量小或者几乎有序的序列。
  • 时间复杂度:
    • 最好 O(n)(已排序)
    • 最坏 O(n²)(逆序)
    • 平均 O(n²)

步骤:

  1. 从第 2 个元素开始(第 1 个默认已排序)。
  2. 比较该元素和已排序序列,从右向左找到合适位置。
  3. 插入该元素,右侧元素后移。
  4. 重复直到排序完成。

3️⃣ 希尔排序 vs 插入排序

特点 插入排序 希尔排序
核心思想 每次插入一个元素到已排序序列 先分组插入排序,逐步减小间隔,最后整体插入
适用情况 小规模或接近有序 大规模数据更优于插入排序
时间复杂度 O(n²) 平均/最坏 最好 O(n log² n) ~ O(n^(3/2))(依增量序列不同)
性能瓶颈 数据量大,逆序时移动次数多 通过"间隔分组"减少元素移动次数
稳定性 稳定 不稳定(同一组元素可能跨组移动)

总结一句话:

希尔排序是"分组插入排序",通过缩小间隔让数组逐步接近有序,从而提高效率。


具体演示

以数组 [8, 5, 3, 7, 6, 2, 4, 1] 来演示 希尔排序 的整个过程。为了简单,采用 gap 序列取 n/2、n/4、...直到 1 的方式,也就是经典做法。


初始数组:

复制代码
[8, 5, 3, 7, 6, 2, 4, 1]

长度 n = 8,初始 gap = 8 / 2 = 4


第 1 轮:gap = 4

分组方式:

  • 第1组:8, 6
  • 第2组:5, 2
  • 第3组:3, 4
  • 第4组:7, 1

对每组进行 插入排序

  1. 第1组 [8, 6] → 排序后 [6, 8]
  2. 第2组 [5, 2][2, 5]
  3. 第3组 [3, 4][3, 4](已排序)
  4. 第4组 [7, 1][1, 7]

合并后,数组变为:

复制代码
[6, 2, 3, 1, 8, 5, 4, 7]

第 2 轮:gap = 2

分组方式:

  • 第1组:6, 3, 8, 4 → [6, 3, 8, 4]
  • 第2组:2, 1, 5, 7 → [2, 1, 5, 7]

分别做插入排序:

  1. 第1组 [6, 3, 8, 4]
    • 插入 3 → [3, 6, 8, 4]
    • 插入 8 → [3, 6, 8, 4](不动)
    • 插入 4 → [3, 4, 6, 8]
  2. 第2组 [2, 1, 5, 7]
    • 插入 1 → [1, 2, 5, 7]
    • 插入 5 → [1, 2, 5, 7](不动)
    • 插入 7 → [1, 2, 5, 7](不动)

合并后,数组变为:

复制代码
[3, 1, 4, 2, 6, 5, 8, 7]

第 3 轮:gap = 1

此时就是普通 插入排序

  • 初始数组:[3, 1, 4, 2, 6, 5, 8, 7]
  • 插入 1 → [1, 3, 4, 2, 6, 5, 8, 7]
  • 插入 4 → [1, 3, 4, 2, 6, 5, 8, 7](不动)
  • 插入 2 → [1, 2, 3, 4, 6, 5, 8, 7]
  • 插入 6 → [1, 2, 3, 4, 6, 5, 8, 7](不动)
  • 插入 5 → [1, 2, 3, 4, 5, 6, 8, 7]
  • 插入 8 → [1, 2, 3, 4, 5, 6, 8, 7](不动)
  • 插入 7 → [1, 2, 3, 4, 5, 6, 7, 8]

最终排序结果:

复制代码
[1, 2, 3, 4, 5, 6, 7, 8]
相关推荐
f3iiish9 小时前
2078. 两栋颜色不同且距离最远的房子 力扣
算法·leetcode
王老师青少年编程9 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【排序贪心】:拼数
c++·算法·贪心·csp·信奥赛·排序贪心·拼数
炽烈小老头9 小时前
【 每天学习一点算法 2026/04/21】螺旋矩阵
学习·算法
未来转换10 小时前
基于A2A协议的生产应用实践指南(Java)
java·开发语言·算法·agent
谭欣辰10 小时前
AC自动机:多模式匹配的高效利器
数据结构·c++·算法
joker_sxj10 小时前
论文阅读-DeepSeek-mHC
论文阅读·算法
历程里程碑10 小时前
MySQL事务深度解析:ACID到MVCC实战+万字长文解析
开发语言·数据结构·数据库·c++·sql·mysql·排序算法
sheeta199810 小时前
LeetCode 每日一题笔记 日期:2026.04.21 题目:1722. 执行交换操作后的最小汉明距离
笔记·算法·leetcode
鲸渔10 小时前
【C++ 跳转语句】break、continue、goto 与 return
开发语言·c++·算法
AI科技星10 小时前
基于螺旋元逻辑的宇宙统一场论底层公理构建(乖乖数学)
算法·机器学习·数学建模·数据挖掘·量子计算