希尔排序:高效插入排序优化版
2026/9/8 19:50:39 网站建设 项目流程

一、前言

希尔排序(Shell Sort)是插入排序的一种高效改进版本,由Donald Shell于1959年提出。插入排序在处理大规模数据时效率较低,因为它每次只能将元素移动一步,导致时间复杂度较高。希尔排序通过引入增量序列(gap),对数据进行分组间隔排序,允许元素大步移动,从而提升性能。核心思路是:从较大的增量开始分组排序,逐步缩小增量,最后当gap=1时执行一次普通插入排序。下面我将逐步讲解其原理、步骤、代码实现,并进行手算模拟


二、希尔排序的核心:增量序列

希尔排序引入一个增量 gap(也称步长),将原序列按索引模 gap 分组,每个组内进行直接插入排序。然后逐步缩小 gap,直到 gap=1,此时整个序列已基本有序,再做一次普通插入排序收尾

常用增量序列:len/2, len/4, ..., 1(取整)


三、详细步骤

希尔排序的执行过程依赖于增量序列的变化。以下步骤基于gap序列(例如gap=4→2→1):

  1. 初始状态:数组无序。
  2. 选择初始gap:计算gap(如len/2),将数组分为gap个组。每组包含间隔为gap的元素(例如,gap=4时,索引差为4的元素为一组)。
  3. 分组排序:对每组执行插入排序(但不是对整个数组排序,而是组内元素进行插入操作)。这一步允许元素在组内大步移动。
  4. 缩小gap:gap缩半(如gap=4→2),重复分组和排序过程。
  5. 最终排序:当gap=1时,执行一次完整的插入排序,完成排序。 整个过程通过分组和缩小gap,逐步减少逆序对数量,提升效率。

四、C语言代码实现

以下代码使用增量序列gap = len/2(缩半),实现希尔排序

#include <stdio.h> void shellSort(int arr[], int n) { // 初始增量 gap = n/2,每次缩半直到 gap=1 for (int gap = n / 2; gap > 0; gap /= 2) { // 对每个分组进行插入排序 for (int i = gap; i < n; i++) { int temp = arr[i]; int j = i; // 组内跳跃式后移 while (j >= gap && arr[j - gap] > temp) { arr[j] = arr[j - gap]; j -= gap; } arr[j] = temp; } } } int main() { int arr[] = {9, 8, 7, 6, 5, 4, 3, 2, 1}; int n = sizeof(arr) / sizeof(arr[0]); shellSort(arr, n); for (int i = 0; i < n; i++) printf("%d ", arr[i]); return 0; }

五、手算模拟

数组 [9, 8, 7, 6, 5, 4, 3, 2, 1] 增量从4→2→1

  • 初始数组: [9, 8, 7, 6, 5, 4, 3, 2, 1]
  • gap=4 (分组排序):
    • 分成4组:组1(索引0,4,8: 9,5,1)、组2(索引1,5: 8,4)、组3(索引2,6: 7,3)、组4(索引3,7: 6,2)。
    • 每组执行插入排序:
      • 组1: [1,5,9](排序后:1,5,9)
      • 组2: [4,8](排序后:4,8)
      • 组3: [3,7](排序后:3,7)
      • 组4: [2,6](排序后:2,6)
    • 数组更新为: [1, 4, 3, 2, 5, 8, 7, 6, 9]
  • gap=2 (分组排序):
    • 分成2组:组1(索引0,2,4,6,8: 1,3,5,7,9)、组2(索引1,3,5,7: 4,2,8,6)。
    • 每组执行插入排序:
      • 组1: [1,3,5,7,9](已有序,不变)
      • 组2: [2,4,6,8](排序后:2,4,6,8)
    • 数组更新为: [1, 2, 3, 4, 5, 6, 7, 8, 9]
  • gap=1 (普通插入排序):
    • 此时数组已基本有序,执行插入排序:比较相邻元素,无需移动。
    • 最终数组: [1, 2, 3, 4, 5, 6, 7, 8, 9] 通过模拟可见,元素从大步移动(如9移动到索引8)到逐步有序。

六、复杂度分析

  • 时间复杂度:平均约为 O(n^(1.3))(依赖于增量序列),最坏情况(如逆序数组)为 O(n^2)。
  • 空间复杂度:O(1)(原地排序,无需额外空间)
  • 稳定性:不稳定。原因在于分组跳跃交换:相同值的元素可能被分到不同组(例如数组中有多个5),排序后相对顺序可能改变。

七、与插入排序对比

插入排序(时间复杂度 O(n^2))每次只移动元素一步,处理大规模数据时效率低;希尔排序通过分组间隔排序,允许元素大步移动(如gap=4时移动4步),显著减少比较和移动次数。希尔排序是插入排序的优化版,在平均情况下性能更优,尤其适用于中等规模数据。

下次我将讲解归并排序(Merge Sort),一种基于分治策略的高效稳定排序算法。敬请期待!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询