排序算法【1】——插入排序
算法描述
插入排序的过程和平时打牌的时候给手里的牌排序差不多:
- 从牌桌上抽一张牌
- 把抽到的牌从右到左(或者从左到右)挨个和手里的牌进行比较,当发现左边的牌大一些,右边的牌小一些,就将牌插入到该位置
- 重复执行步骤1,直到牌抽完了
参考动画:visualgo.net
代码实现(C++)
#include <algorithm>
#include <utility>
/**
* 对范围[first, last)的元素进行插入排序
* @param first 双向迭代器开头
* @param last 双向迭代器结尾
* @param comp 比较函数
*/
template<typename BidirectionalIterator, typename Compare>
void insertionSort(BidirectionalIterator first, BidirectionalIterator last, Compare comp) {
if (first != last) {
// [first, sortedEnd)表示目前已经排好序的范围
for (auto sortedEnd = first; ++sortedEnd != last;) {
if (comp(*sortedEnd, *first)) {
// 当前元素val应该排在第一位
auto val = std::move(*sortedEnd);
auto next = sortedEnd;
std::move_backward(first, sortedEnd, ++next);
*first = std::move(val);
} else {
// prev表示当前元素val所在正确位置的前一个位置
auto prev = sortedEnd;
--prev;
auto next = sortedEnd;
auto val = std::move(*sortedEnd);
while (comp(val, *prev)) {
*next = std::move(*prev);
next = prev;
--prev;
}
*next = std::move(val);
}
}
}
}
算法复杂度
对于排序算法而言,它并不会关心自己处理的数据具体代表什么,而只关心数据之间的大小关系。所以对于任意一组数据,都可以将里面的元素抽象成其在整组数据里面的大小排名(rank)。简单起见,这里假设所有元素大小均不相同,于是任一组数据便可对应于集合的一种排列。
然后引入逆序对(invertion pair)的概念:
定义:在数列中若存在下标使得 A[i]>A[j] ,则称为一个逆序对。数列中逆序对的总数为逆序数
显然数组的逆序数能很好地描述该数组的无序程度。而且不难看出的是一组数据的逆序数刚好就是插入排序需要执行的比较移动操纵的次数。因为在进行元素的插入时,每一次比较出元素该再往前一步时,随着较大的元素后移一步恰好就修复了一个逆序对。
- 最好情况:当数组本身有序时,逆序数为0,时间复杂度为
- 最坏情况:当数组本身逆序时,逆序数为,时间复杂度为
- 平均情况:当数组随机排列时,令随机变量表示逆序数,那么期望值,时间复杂度为
期望值求解过程:
令随机变量
则
很明显是逆序对的概率是,所以期望也是
总结
- 对于近乎有序的数据而言插入排序算法十分高效。
- 对于规模很小的数据插入排序也是极佳的选择,由于其所进行的操作很简单所以平均每次操作的开销都很小。这一点使得像快速排序以及归并排序等算法都用插入排序来处理自己划分出来的小区间以优化性能。
- 插入排序是稳定的排序算法,即不改变相同大小元素的原始次序关系。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)