跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

数据结构与算法:深入理解希尔排序

综述由AI生成希尔排序是插入排序的优化版本,核心在于引入“增量(Gap)”概念。它允许元素跳跃式移动,解决了普通插入排序在尾部小元素前移时效率低下的问题。通过分组跳跃、逐步缩小间隔,最终在数组基本有序时完成排序。该算法空间复杂度为 O(1),但不稳定,适用于中等规模数据及内存敏感场景。

游戏玩家发布于 2026/4/9更新于 2026/5/2212 浏览
数据结构与算法:深入理解希尔排序

概念

希尔排序 = 插入排序 + 分组跳跃

它不是一次只和前面相邻的元素比,而是先隔着很远比,然后慢慢缩小距离,最后变成普通的插入排序。

为什么需要希尔排序?

简单插入排序有个明显的软肋:当较小的数都堆在数组尾部时,排序效率会很低。因为插入排序每次只能交换相邻元素,要把尾部的小数挪到前面,需要一步一步'冒泡'过去,非常耗时。

看一下插入排序的代码逻辑:

public static void insertionSort(int[] arr) {
    int len = arr.length;
    for (int i = 1; i < len; i++) {
        int j = i;
        int temp = arr[j];
        while (j > 0 && arr[j - 1] > temp) {
            // 如果前一个元素比当前元素大,则将前一个元素向后移动一位
            arr[j] = arr[j - 1];
            j--;
        }
        arr[j] = temp;
    }
}

而希尔排序通过引入增量(Gap)的概念,允许元素跳跃式移动,让小数能更快地'蹦'到前面,从而解决了这一问题。

核心原理

核心概念:增量(Gap)

希尔排序引入了一个间隔 gap,它不是让元素和相邻的比,而是和相隔 gap 个位置的元素比。

过程分三步:
  1. 分组:按 gap 把数组分成若干组
  2. 组内插入排序:对每组分别做插入排序
  3. 缩小 gap:gap 减半,重复上述过程,直到 gap = 1

当 gap = 1 时,就是普通的插入排序,但此时数组已经基本有序,插入排序会非常快。

代码实现

public static void shellSort(int[] arr) {
    int n = arr.length;
    // 外层循环:控制 gap 从 n/2 开始,每次减半
    for (int gap = n / 2; gap > 0; gap /= 2) {
        // 内层循环:对每个分组做插入排序
        // 注意这里从 gap 开始,而不是从 1 开始
        for (int i = gap; i < n; ++i) {
            int key = arr[i];
            int j = i - gap;
            // 和前面相隔 gap 的元素比较
            while (j >= 0 && arr[j] > key) {
                arr[j + gap] = arr[j]; // 大的往后挪 gap 个位置
                j -= gap;              // 往前跳 gap 个位置继续比
            }
            arr[j + gap] = key; // 插入到正确位置
        }
    }
}

插入排序 vs 希尔排序 对比

插入排序希尔排序
for (int i = 1; i < n; ++i)for (int gap = n/2; gap > 0; gap/=2)
for (int i = 1; i < n; ++i)for (int i = gap; i < n; ++i)
int j = i - 1;int j = i - gap;
while (j >= 0 && arr[j] > key)while (j >= 0 && arr[j] > key)
arr[j + 1] = arr[j];arr[j + gap] = arr[j];
j -= 1;j -= gap;
arr[j + 1] = key;arr[j + gap] = key;

唯一的区别:把插入排序里的 1 全部换成了 gap,再套一层 gap 递减的循环。

图解演示

数组:[80, 93, 60, 12, 42, 30, 68, 85, 10]

第一轮:gap = 4

把相隔 4 个位置的元素分为一组:

  • 组 1 (▲): 80, 42, 10 → 下标 0, 4, 8
  • 组 2 (●): 93, 30 → 下标 1, 5
  • 组 3 (■): 60, 68 → 下标 2, 6
  • 组 4 (◆): 12, 85 → 下标 3, 7

对每组分别做插入排序:

  • 组 1 排序后:10, 42, 80
  • 组 2 排序后:30, 93
  • 组 3 排序后:60, 68
  • 组 4 排序后:12, 85

放回原数组:

排序前:[80, 93, 60, 12, 42, 30, 68, 85, 10]
排序后:[10, 30, 60, 12, 42, 93, 68, 85, 80]

观察:最小的 10 从最后一位(下标 8)跳到了第一位(下标 0)!一步跨了 8 个位置,这就是希尔排序的效率来源。

第二轮:gap = 2

当前:[10, 30, 60, 12, 42, 93, 68, 85, 80]
分组:
组 1 (▲): 10, 60, 42, 68, 80 → 下标 0,2,4,6,8
组 2 (●): 30, 12, 93, 85 → 下标 1,3,5,7

分别插入排序后放回:

排序前:[10, 30, 60, 12, 42, 93, 68, 85, 80]
排序后:[10, 12, 42, 30, 60, 85, 68, 93, 80]

第三轮:gap = 1

就是普通的插入排序:

排序前:[10, 12, 42, 30, 60, 85, 68, 93, 80]
排序后:[10, 12, 30, 42, 60, 68, 80, 85, 93]

此时数组已经基本有序,插入排序只需要很少的移动就能完成。

注意排序时,每一组元素只在属于自己组的下标位置之间进行排序和交换,完全不碰其他组的元素。简单来说,这一组数就是在原来数组的这一组的基础之上排序换位置,而其他组的位置丝毫不影响,只在自己的那个 gap 组里面换。

复杂度与特点

特性说明
时间复杂度取决于 gap 序列,经典希尔增量 O(n²),优化序列可达 O(n^1.3)
空间复杂度O(1),原地排序
稳定性不稳定(跳跃式交换可能打乱相同元素的顺序)
适用场景中等规模数据,嵌入式设备等内存敏感场景

一句话总结:希尔排序 = 带间隔的插入排序,通过"大步跳跃 + 逐步逼近"来优化小数后移的问题。

目录

  1. 概念
  2. 为什么需要希尔排序?
  3. 核心原理
  4. 核心概念:增量(Gap)
  5. 过程分三步:
  6. 代码实现
  7. 插入排序 vs 希尔排序 对比
  8. 图解演示
  9. 第一轮:gap = 4
  10. 第二轮:gap = 2
  11. 第三轮:gap = 1
  12. 复杂度与特点
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • DFT 中的 On-Chip Clock Controller (OCC) 架构设计与插入规则
  • AIGC 技术发展与应用实践指南
  • AI 编程模型深度对比:实现高效开发的选型策略
  • Web 自动化测试入门:从概念到百度搜索实战
  • C++ 实现 2048 小游戏核心逻辑解析
  • 医学影像分类器实践:基于深度学习的肺结节检测
  • AI 辅助贪吃蛇游戏开发实战
  • Rust 语言入门:从环境搭建到发布第一个 CLI 工具
  • Chaterm:开源 AI 智能终端与 SRE 协作工具
  • LangChain 中基于图论实现多 Agent 的利器:LangGraph
  • Java 环境配置与第一个 Hello World 程序实战
  • 注意力机制与 Transformer 模型实战
  • C++ 模板初阶
  • 双向循环链表原理与 C 语言实现
  • 2026 年毕业论文 AI 检测标准及各高校红线汇总
  • 全国计算机等级考试(二级 Web 程序设计)安排与例题解析
  • RabbitMQ/Spring-AMQP 高级特性:事务机制与消息限流
  • 2025 年 AIGC 六大核心趋势解析
  • Adoptium Temurin JDK 下载与多平台配置指南
  • 快速排序核心原理与多版本实现详解

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online