希尔排序详解

希尔排序是插入排序的一种更高效的改进版本,也称为"缩小增量排序"


前言

希尔排序的核心思想是:使数组中任意间隔为 gap 的元素都是有序的。这样的数组被称为是 gap 有序 的,基本思路:先将整个待排序的序列分割成若干个子序列,分别进行直接插入排序。待整个序列中的记录"基本有序"时,再对全体记录进行一次直接插入排序,如何分割? 通过一个增量序列(Gap Sequence) 来控制。增量逐渐减小,最终减至 1(即对整个数组进行最后一次标准的插入排序)

**我们以数组 [8, 9, 1, 7, 2, 3, 5, 4, 6, 0] 为例,详细演示希尔排序的每一步过程,**数组长度 n = 10,使用希尔增量序列:gap = 5 → 2 → 1

排序后数组: [3, 5, 1, 6, 0, 8, 9, 4, 7, 2]

第2轮:gap = 2

排序后数组: [0, 2, 1, 4, 3, 5, 7, 6, 9, 8]

第3轮:gap = 1

对整个数组进行标准插入排序:数组:[0, 2, 1, 4, 3, 5, 7, 6, 9, 8]

最终排序结果: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

实现希尔排序

cpp 复制代码
void shellSort(int arr[], int n) {
   int gap=n/2;
     while (gap > 0) {
        for (int i = gap; i < n; i++) {
            int temp = arr[i];
            int j = i - gap;  // 从前一个位置开始
            
            while (j >= 0 && arr[j] > temp) {
                arr[j + gap] = arr[j];  // 向后移动
                j -= gap;
            }
            arr[j + gap] = temp;  // 插入到正确位置
        }
        gap /= 2;
    }
}
cpp 复制代码
初始数组: 8 9 1 7 2 3 5 4 6 0 
=== 第1轮排序,gap = 5 ===
处理元素 arr[5] = 3: 8 9 1 7 2 [3] 5 4 6 0 
  移动 arr[0](8) -> arr[5]
  插入 3 到位置 0
  当前数组: 3 9 1 7 2 8 5 4 6 0 
处理元素 arr[6] = 5: 3 9 1 7 2 8 [5] 4 6 0 
  移动 arr[1](9) -> arr[6]
  插入 5 到位置 1
  当前数组: 3 5 1 7 2 8 9 4 6 0 
处理元素 arr[7] = 4: 3 5 1 7 2 8 9 [4] 6 0 
  移动 arr[2](1) -> arr[7]
  插入 4 到位置 2
  当前数组: 3 5 4 7 2 8 9 1 6 0 
处理元素 arr[8] = 6: 3 5 4 7 2 8 9 1 [6] 0 
  移动 arr[3](7) -> arr[8]
  插入 6 到位置 3
  当前数组: 3 5 4 6 2 8 9 1 7 0 
处理元素 arr[9] = 0: 3 5 4 6 2 8 9 1 7 [0] 
  移动 arr[4](2) -> arr[9]
  插入 0 到位置 4
  当前数组: 3 5 4 6 0 8 9 1 7 2 
本轮排序后: 3 5 4 6 0 8 9 1 7 2 

=== 第2轮排序,gap = 2 ===

=== 第3轮排序,gap = 1 ===

最终排序结果: 0 1 2 3 4 5 6 7 8 9 

总结

希尔排序通过将大规模数组先调整为"基本有序"的状态,极大地减少了最后一次插入排序的比较和移动次数,从而提升了整体性能。它是一种非常巧妙的算法,虽然在实际应用中已被更高效的算法所取代,但其思想仍然非常值得学习和借鉴。它很好地展示了如何通过预处理来优化一个简单算法

相关推荐
荆棘鸟智能1 分钟前
AI算法持续学习与迭代怎么做?从数据闭环到灰度发布的MLOps工程实践
人工智能·算法·架构·边缘计算
Lyyaoo.6 分钟前
【二分查找】【中等】搜索二维矩阵/排序数组的第一位和最后位置/搜索旋转排序数组/旋转排序数组中的最小值
java·数据结构·算法
土司大王14 分钟前
LeetCode hot100——153.寻找旋转排序数组中的最小值:Java 二分模板与 O(log n) 分析
java·算法·leetcode
光电的一只菜鸡16 分钟前
isp中关于锐化对图像清晰度的影响
算法
土司大王37 分钟前
LeetCode hot100——4.寻找两个正序数组的中位数:Java 二分第K小 递归裁剪
java·算法·leetcode
薛定e的猫咪42 分钟前
(ICML2024)QSM:基于 Q 函数梯度对齐分数场的扩散模型离策略强化学习
人工智能·深度学习·算法
hetao17338371 小时前
2026-09-13 hetao1733837 的刷题记录
c++·算法
hansang_IR1 小时前
【题解】[JSOI2016] 扭动的回文串
c++·算法
Lyyaoo.1 小时前
【二分查找】【困难】寻找两个有序数组的中位数
java·数据结构·算法
有点。1 小时前
C++03阶段练习(一)
数据结构·c++