当前位置: 首页 > news >正文

C 语言希尔排序:原理、实现与性能深度解析

在排序算法的大家族中,希尔排序是插入排序的 “进阶版”,它通过引入 “增量” 概念,大幅提升了插入排序在大规模数据场景下的效率。本文将结合 C 语言代码实例,从原理、实现步骤到性能分析,带你全面掌握希尔排序。

一、希尔排序的核心原理:打破 “相邻比较” 的局限

要理解希尔排序,首先得回顾它的 “前身”—— 直接插入排序。直接插入排序的核心是 “将待排序元素插入到已排序序列的合适位置”,但它只能逐个比较相邻元素,若数据逆序程度高(比如要把最小元素移到最前面),需要大量移动操作,时间复杂度高达 O (n²)。

希尔排序的改进思路很巧妙:先将整个数组按 “增量” 分成多个子数组,对每个子数组进行直接插入排序;然后逐步缩小增量,重复子数组排序操作;直到增量缩小为 1,此时对整个数组进行最后一次直接插入排序,算法结束

这里的 “增量” 是关键:

  • 初始增量通常取数组长度的一半(如数组长度为 10,初始增量为 5);
  • 每次增量缩小为前一次的一半(5→2→1);
  • 增量为 1 时,数组已基本有序,最后一次插入排序的效率会极高。

二、基于 C 语言的希尔排序实现(附代码解析)

我们以你提供的代码为基础,逐行拆解希尔排序的实现逻辑。代码功能是对一个包含 10 个整数的数组进行排序,并打印结果。

1. 完整代码

#include <stdio.h>

#include <string.h> // 此处strlen未使用,可删除以优化代码

int main (){

// 1. 定义待排序数组

int arr[10]={1,22,33,4,5,6,75,78,9,0};

// 2. 计算数组长度(避免硬编码,提高通用性)

int len=sizeof(arr)/sizeof(arr[0]);

// 3. 希尔排序核心:外层循环控制增量缩小

for(int i=len/2;i>0;i/=2){ // 初始增量=len/2,每次减半,直到i=0时退出

// 4. 中层循环:按当前增量分组,遍历每组的待插入元素

for(int j=i;j<len;j+=i){ // j从增量位置开始,每次加增量遍历同组元素

// 5. 记录当前待插入的元素(避免后续移动时被覆盖)

int target=arr[j];

// 6. 内层循环:在当前子数组中,向前比较并移动元素

int b=j-i; // b是当前元素前一个同组元素的下标

// 当b>=0(未越界)且待插入元素小于前一个元素时,继续向前找

while(b>-1&&target<arr[b]){

arr[b+i]=arr[b]; // 将前一个元素向后移动增量位置

b-=i; // 继续向前遍历同组元素

}

// 7. 找到合适位置,插入待排序元素

arr[b+i]=target;

}

}

// 8. 打印排序后的数组

for(int c=0;c<10;c++)

printf("%d ",arr[c]);

return 0;

}

2. 关键步骤拆解

我们以数组arr[10] = {1,22,33,4,5,6,75,78,9,0}为例,结合增量变化,看排序过程:

步骤 1:初始增量 i=5(len/2=10/2=5)

此时数组按增量 5 分成 5 组:(arr[0],arr[5])、(arr[1],arr[6])、(arr[2],arr[7])、(arr[3],arr[8])、(arr[4],arr[9]),对每组进行直接插入排序:

  • 组 1:[1,6] → 无需排序;
  • 组 2:[22,75] → 无需排序;
  • 组 3:[33,78] → 无需排序;
  • 组 4:[4,9] → 无需排序;
  • 组 5:[5,0] → 排序后为 [0,5];
  • 第一次排序后数组:{1,22,33,4,0,6,75,78,9,5}。
步骤 2:增量 i=2(5/2=2,整数除法)

按增量 2 分成 2 组:(arr[0],arr[2],arr[4],arr[6],arr[8])、(arr[1],arr[3],arr[5],arr[7],arr[9]),每组插入排序:

  • 组 1:[1,33,0,75,9] → 排序后为 [0,1,9,33,75];
  • 组 2:[22,4,6,78,5] → 排序后为 [4,5,6,22,78];
  • 第二次排序后数组:{0,4,1,5,9,6,33,22,75,78}。
步骤 3:增量 i=1(2/2=1)

此时增量为 1,对整个数组进行直接插入排序(数组已基本有序,仅需少量移动):

  • 最终排序结果:{0,1,4,5,6,9,22,33,75,78}。

三、希尔排序的性能分析

希尔排序的性能不像直接插入排序(固定 O (n²))那样容易界定,它的时间复杂度与 “增量序列” 的选择密切相关,空间复杂度则非常稳定。

1. 时间复杂度

希尔排序的时间复杂度是非稳定的,取决于增量如何缩小:

  • 最坏情况:若增量序列选择不当(如每次增量为前一次的 2 倍减 1),时间复杂度可能达到 O (n²)(但实际仍优于直接插入排序,因为数组提前被 “预处理” 为近似有序);
  • 平均情况:在常用的 “增量 = len/2,每次减半” 策略下,平均时间复杂度约为O(n^1.3)(这是通过大量实验统计得出的结果,而非严格数学证明);
  • 最优情况:若数组本身已有序,时间复杂度可接近 O (n)(仅需遍历,无需大量移动元素)。

需要注意的是,你代码中注释的 “O (n³)” 是错误的 —— 内层 while 循环的执行次数随增量缩小而减少,整体嵌套循环的时间复杂度远低于 O (n³),实际应参考上述分析。

2. 空间复杂度

希尔排序是原地排序算法,仅需额外定义 3 个变量(len、target、b),与数组规模 n 无关,因此空间复杂度为O(1)

3. 稳定性

希尔排序是不稳定排序。例如,数组{3, 3, 1}按增量 2 分组时,第一个 3(下标 0)和第二个 3(下标 1)会被分到不同组,排序后可能导致两个 3 的相对位置发生变化。

四、希尔排序的优化方向

你提供的代码已实现希尔排序的核心逻辑,但仍有优化空间:

  1. 优化增量序列

目前使用的 “len/2” 增量序列虽然简单,但并非最优。更高效的增量序列如 “Hibbard 序列”(1, 3, 7, ..., 2^k-1)或 “Sedgewick 序列”(1, 5, 19, 41, ...),可将平均时间复杂度进一步降低到 O (n^1.2) 甚至更低。

  1. 删除无用头文件

代码中#include <string.h>未使用(strlen用于字符串长度计算,与 int 数组无关),删除后可减少编译依赖。

  1. 增加通用性

可将排序逻辑封装为函数(如void shellSort(int arr[], int len)),支持任意长度的 int 数组排序,提高代码复用性。

五、总结

希尔排序是一种 “性价比很高” 的排序算法:

  • 实现简单,仅需在直接插入排序的基础上增加增量控制;
  • 效率优于直接插入排序、冒泡排序等基础排序算法,适合中等规模数据排序;
  • 原地排序,空间开销小,在内存有限的场景下优势明显。

如果你需要进一步优化代码(如实现 Hibbard 增量序列),或想了解希尔排序与快速排序、归并排序的性能对比,欢迎补充需求,我们可以继续深入探讨!

http://www.dtcms.com/a/617653.html

相关文章:

  • 【期末网页设计作业】HTML+CSS+JS 电影网站设计与实现 影视主题网站(附代码)
  • react 的状态管理
  • 世界上最有趣的网站外贸稳中提质韧性强
  • 简单理解:DCDC(直流 - 直流转换器)和LDO(低压差线性稳压器)
  • 电科金仓国产数据库KingBaseES深度解析:五个一体化的技术架构与实践指南
  • 2025卷【答案】
  • 防止网站被克隆买完网站怎么建设
  • 搭建Python开发环境
  • Vue 项目实战《尚医通》,预约挂号底部医生排班业务,笔记39
  • Firefly 结构与样式参考:AI 重构品牌广告工作流
  • 在 Ubuntu 22.04 上安装和配置 Nginx 的完整指南
  • 网站开发需要的技能线上网站建设需求
  • 如何实现中药饮片采购的高效联动以提升行业透明度?
  • Redis(127)Redis的内部数据结构是什么?
  • 十七:Spring Boot依赖 (2)-- spring-boot-starter-web 依赖详解
  • Protocol Buffers (Protobuf) 详解
  • 沁水网站建设吉林省 网站建设
  • 正能量晚上看的网站2021网站优化客户报表
  • 智慧交通自动驾驶场景道路异常检测数据集VOC+YOLO格式8302张6类别
  • 内联函数(Inline Functions)详细讲解
  • CentOS Stream 8 通过 Packstack 安装开源OpenStack(V版本)
  • 企业实训|自动驾驶中的图像处理与感知技术——某央企汽车集团
  • 电子商城网站建设流程外链系统
  • 数据分析笔记10:数据容器
  • 基于Django的博客系统
  • 地图引擎性能优化:解决3DTiles加载痛点的六大核心策略
  • 树莓派5-ubuntu24.04 LTS 使用python构建雷达驱动包
  • Django Nginx+uWSGI 安装配置指南
  • php网站建设培训班如何在word里做网站
  • 用Rust从零实现一个迷你Redis服务器