嵌入式 - 数据结构与算法:(1-13)排序算法 - 希尔排序(Shell Sort)

上一篇 下一篇
快速排序

目 录


4)希尔排序(Shell Sort)

希尔排序,又称 "缩小增量排序",是插入排序的一种高效改进版本,由 Donald Shell 于 1959 年提出

参考视频:数据结构合集 - 希尔排序(算法过程, 效率, 稳定性分析)_哔哩哔哩_bilibili

4.1)核心思想

插入排序简介:(将数组分为"已排序"和"未排序"两部分)初始时,第一个元素视为已排序。然后依次从"未排序"部分取出元素,插入到"已排序"部分的正确位置(当比左边的大,比右边的小,则就到了正确的位置),直到所有元素都被处理。

希尔排序核心思想: 先让数组"大致有序",再进行一次精细的插入排序

它通过引入一个 间隔(gap) ,将原始数组划分为若干个子序列,对每个子序列分别进行插入排序。随着 gap 逐步缩小(通常每次除以 2),子序列越来越长,数组也越来越接近有序。当 gap = 1 时,就退化为一次标准的插入排序------但此时数据已基本有序,效率极高。

4.2)算法步骤(升序)

  1. 选择一个初始 间隔 gap (通常取 n / 2,n 为数组长度,向下取整);
  2. 将数组按 gap 分成若干组(例如 gap=3,则索引 0,3,6... 为一组;1,4,7... 为一组等);
  3. 对每组内部进行 插入排序
  4. 缩小 gap(如 gap = gap / 2);
  5. 重复步骤 2~4,直到 gap = 1
  6. 最后执行一次 gap = 1 的插入排序,完成整体排序。

关键优势:提前将大数"快速"移到后面,小数"快速"移到前面,避免插入排序在逆序时大量移动。

4.3)时间与空间复杂度

情况 时间复杂度(依赖 gap 序列)
最好 O(n log n)
平均 O(n^1.3) ~ O(n^(3/2))(常用 gap=n/2 时)
最坏 O(n²)(某些 gap 序列下)
  • 空间复杂度:O(1)(原地排序)
  • 稳定性:❌ 不稳定(跨组交换可能改变相等元素顺序)

注意:希尔排序的时间复杂度 依赖于 gap 序列的选择 ,常见 gap 序列:

  • Shell 原始:n/2, n/4, ..., 1
  • Knuth:1, 4, 13, 40, ...(公式:gap = gap * 3 + 1
  • Sedgewick 等更优序列(工程中较少用)

4.4)C 语言代码示例

(使用 Shell 原始 gap 序列)

c 复制代码
#include <stdio.h>

/* 希尔排序函数(升序)*/
void shell_sort(int arr[], int n) {
    // 初始 gap 为数组长度的一半
    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; // 插入到正确位置
        }
    }
}

// 打印数组
void print_array(int arr[], int n) {
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

/* 主函数:测试希尔排序 */
int main() {
    int arr[] = {64, 34, 25, 12, 22, 11, 90};
    int n = sizeof(arr) / sizeof(arr[0]);

    printf("原始数组: ");
    print_array(arr, n);

    shell_sort(arr, n);

    printf("排序后数组: ");
    print_array(arr, n);

    return 0;
}

运行结果如下:

复制代码
原始数组: 64 34 25 12 22 11 90 
排序后数组: 11 12 22 25 34 64 90 

执行过程示例(简略):

  • gap = 3 → 分组:
    [64, 12, 90], [34, 22], [25, 11] → 各组插入排序后 → [12, 22, 11, 64, 34, 25, 90]
  • gap = 1 → 整个数组插入排序 → 最终有序

相关推荐
北域码匠3 小时前
高通滤波算法深度解析(High-Pass Filter)
stm32·算法·c#·数字信号处理·嵌入式开发·滤波算法·高通滤波
指掀涛澜天下惊4 小时前
强化学习进阶篇八 策略梯度算法
深度学习·学习·算法·强化学习
乌萨奇也要立志学C++4 小时前
【洛谷】kmp算法
开发语言·算法
禹凕4 小时前
Dijkstra算法详解与应用
python·算法
YaraMemo5 小时前
元启发式算法框架
人工智能·算法·5g·信息与通信·启发式算法·信号处理
weixin_307779135 小时前
一维无粘 Burgers 方程的激波形成问题:MacCormack 格式求解
c++·算法·matlab
HugoStudio_SWAN5 小时前
洛谷 B4500 / B4449 / B3843 凯撒密码、密码强度与密码合规——加密与安全的三道门
c++·学习·程序人生·算法·安全
枫叶林FYL6 小时前
【群体智能集群控制工程实践】第3章 一致性协同算法
算法
禹凕7 小时前
滑动窗口算法实战指南
python·算法
DisonTangor7 小时前
【腾讯混元雪耻归来】 Hy4 preview:770B 参数 MoE 旗舰模型,1M 上下文全面开源
人工智能·算法·开源·aigc·腾讯云·腾讯云ai代码助手