嵌入式 - 数据结构与算法:(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 → 整个数组插入排序 → 最终有序

相关推荐
无限码力14 分钟前
阿里算法岗 0530笔试真题 - 多约束条件下的元素匹配统计
算法·阿里笔试真题·阿里机试真题·阿里算法岗笔试
lqqjuly22 分钟前
MLA — 多头潜在注意力深度解析
深度学习·神经网络·算法
吴可可12343 分钟前
SolidWorks草图转三维DWG技巧
算法
用户484526255821 小时前
数组分区和荷兰国旗只差一个条件:稳定性
排序算法
redaijufeng1 小时前
C++雾中风景7:闭包
c++·算法·风景
小欣加油2 小时前
leetcode287寻找重复数
数据结构·c++·算法·leetcode
尽兴-2 小时前
2.1 向量基础:Embedding、余弦相似度、欧氏距离、向量检索
算法·embedding·欧氏距离·向量检索·余弦相似度
Black蜡笔小新2 小时前
自动化AI算法训练服务器DLTM训推一体工作站赋能多行业智能化升级
人工智能·算法·自动化
怪兽学LLM3 小时前
LeetCode 438 找到字符串中所有字母异位词(Python 固定滑动窗口+字符计数解法)
python·算法·leetcode
满怀冰雪3 小时前
第04篇-双指针算法-从有序数组到回文判断的高频解法
java·算法