从“理扑克牌”到“分组优化”——直接插入排序与希尔排序详解

一、引言

排序(Sorting)是计算机科学中最基础、应用最广的算法之一。

想想这些场景:

  • 从通讯录里找一个人 → 按姓氏排序后,二分查找秒到

  • 淘宝按价格从低到高筛选商品 → 价格排序

  • 考试后按分数排名 → 成绩排序

如果没有排序,这些操作都会变得极其低效。

本篇文章是排序系列的第一篇 ,我会带你从最简单、最直观的直接插入排序 开始,然后逐步递进到它的升级版------希尔排序

学完这篇,你不仅能掌握这两种排序的实现,还能理解一个非常重要的算法设计思想:如何从朴素的思路出发,通过"预排序"来优化性能

二、直接插入排序

核心思想

直接插入排序的核心思想,可以用一个生活场景完美解释------理扑克牌

当你打牌时,会一张一张摸牌,每摸到一张新牌,你会从右向左跟手里已有的牌比较,找到合适的位置插进去,始终保持手里的牌是有序的。

  • 将待排序的数据分为"已排序区间"和"未排序区间"。每次从未排序区间取出第一个元素,插入到已排序区间中的正确位置,使已排序区间仍然保持有序。

下面我们来画图理解

理解了直接插入排序的思想之后,我们来用代码实现一下

cpp 复制代码
void InsertSort(int* arr, int n)
{
	for (int i = 0;i < n - 1;i++)
	{
		int end = i;
		int tmp = arr[end + 1];
		while (end >= 0)
		{
			if (arr[end] > tmp)
			{
				arr[end + 1] = arr[end];
				end--;
			}
			else
			{
				break;
			}
		}
		arr[end + 1] = tmp;
	}
}

接下来我们来分析一下直接插入排序的时间复杂度:

情况 复杂度 说明
最好(数组已经有序) O(n) 每个元素只比较一次,不移动
最坏(数组逆序) O(n²) 第 i 个元素需要比较 i 次,总次数 = 1+2+...+(n-1) ≈ n²/2
平均 O(n²) 随机数据,平均比较和移动约 n²/4

平均O(n²)的时间复杂度太高了,面对无序且大量的数据,直接插入排序的效率很低,因此在此排序思想的基础上,又演变出了一种更加高效的排序方法:希尔排序

三、希尔排序

核心思想

希尔排序也叫**"缩小增量排序"**(Diminishing Increment Sort)。它的核心思想是:

先进行"预排序",让数组变得"基本有序",最后再进行一次直接插入排序。

怎么预排序?------按间隔分组

例如图中的一组数据,我们以 gap = 4 的间隔来分组,可以分为四个组。

对每一组分别进行插入排序 。这样,元素就可以一次跨越 gap 步到达相对正确的位置。

预排序完成后,缩小 gap,继续分组排序......直到 gap = 1,此时就是标准的直接插入排序。但因为数组已经基本有序,插入排序的效率很高(接近 O(n))。

对于 gap,我们通常让 gap = gap / 3 + 1

下面是希尔排序的代码实现

cpp 复制代码
void ShellSort(int* arr, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (int i = 0;i < n - gap;i++)
		{
			int end = i;
			int tmp = arr[end + gap];
			while (end >= 0)
			{
				if (arr[end] > tmp)
				{
					arr[end + gap] = arr[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			arr[end + gap] = tmp;
		}
	}
}

时间复杂度的分析:

情况 复杂度 说明
最好 O(n log n) 数据基本有序时
最坏 O(n²) 取决于 gap 序列,某些序列可避免 O(n²)
平均 O(n^1.3 ~ n^1.5) 远优于 O(n²)

由此可见,在优化后的希尔排序比优化之前的直接插入排序时间复杂度要小很多,这就是这种预排序思想所带来的好处

五、总结

一句话记住这两种排序:

直接插入排序 :像理扑克牌,一张一张插入到正确位置。

希尔排序:先分组排序让数组"大概有序",再最后插入排序收尾。

建议:

  1. 先熟练掌握直接插入排序

  2. 理解希尔排序的"预排序 + 最终插入"思想------这是重要的算法设计思路

  3. 一定要手写一遍代码,感受两种排序的异同

相关推荐
尾善爱看海18 分钟前
前端算法与手写题集
前端·算法
程序员阿鹏1 小时前
为什么MySQL InnoDB选择B+树?
数据结构·数据库·b树·sql·mysql·算法·缓存
AI 思录1 小时前
Prompt 事故档案(八):日常表达被标为“待校准”,AI 的爹味语法从哪里来
大数据·人工智能·算法·prompt·用户体验·ai合规
月光船幽幽1 小时前
跨范式映射的稳定接口设计
人工智能·python·算法
郝学胜-神的一滴3 小时前
C++11 工程级应用 09:告别无谓拷贝,解锁高性能移动语义
开发语言·数据结构·c++·vscode·软件工程·visual studio
2601_965742223 小时前
全媒体运营与短视频代运营,两者有什么区别?
大数据·数据结构·人工智能·算法·ai·媒体
wordbaby4 小时前
混合检索:两全其美的艺术
人工智能·算法
彧azz4 小时前
数据结构:关于图的学习
c语言·数据结构·笔记·学习·算法
热心网友俣先生4 小时前
A题-药材的烘干问题-题意逐句翻译
算法·数学建模
2601_960356384 小时前
2026秋招运营分析师能力模型:SQL、指标体系、AIGC与业务分析
算法