内部排序-直接插入排序
写在前面:参考《数据结构(C语言版)》严蔚敏 吴伟民 编著 清华大学出版社 2008年10月第27次印刷
📋 算法概述
直接插入排序(Straight Insertion Sort)是一种最简单的排序方法,它的基本操作是将一个记录插入到已排号序的有序表中,从而得到一个新的、记录数增1的有序表。
🎯 算法特点
特性 | 说明 |
---|---|
稳定性 | 稳定排序算法 |
原地排序 | 是,只需要常数级的额外空间,所以空间复杂度为O(1) |
最佳情况 | O(n) - 当输入数据已经是正序时 |
最差情况 | O(n²)- 当输入数据是反序时 |
平均情况 | O(n²) - 所以时间复杂度为O(n²) |
🔍 算法原理
tips:联想我们在打扑克的时候,整理手牌的过程。目前手上有5张牌,分别是黑桃7、黑桃8、黑桃6、黑桃10和黑桃5。现在需要按照从小到大的顺序排列。
- 将第一个元素视为已排序序列:黑桃7
- 从下一个元素开始,视为待插序列key:黑桃8
- 将待插序列key与已排序序列从后向前对比:黑桃8对比黑桃7
4. 待插序列key大于或等于已排序列:若对比到第一个元素,则跳到步骤2;其它则重复步骤3
2. 待插序列key小于已排序列:黑桃6对比黑桃8,则将黑桃8向后移动一位。此时序列:黑桃7、空隙、黑桃8、黑桃10和黑桃5。重复步骤3 - 重复步骤23:此时序列:黑桃6、黑桃7、黑桃8、黑桃10和黑桃5
- 终止条件:重复步骤23,直到所有元素都插入到正确位置。此时序列:黑桃5、黑桃6、黑桃7、黑桃8和黑桃10
💻 C# 实现代码
🚀示例
/// <summary>/// 对 list 直接插入排序 从小到大/// </summary>/// <param name="list">数据列表</param>private void StraightInsertionSort(List<int> list){if (list == null || list.Count == 0) return;/**初始化:49, 38, 99, 13, 49, 57* 第一趟: 38, 49, 99, 13, 49, 57* 第二趟: 38, 49, 99, 13, 49, 57* 第三趟: 38, 49, 空, 99, 49, 57* 第三趟: 38, 空, 49, 99, 49, 57* 第三趟: 空, 38, 49, 99, 49, 57* 第三趟: 13, 38, 49, 99, 49, 57* 第四趟: 13, 38, 49, 49, 99, 57* 第五趟: 13, 38, 49, 49, 57, 99*/for (int i = 1; i < list.Count; i++){int current = list[i];int j = i - 1;// 移动元素而不是交换while (j >= 0 && list[j] > current){list[j + 1] = list[j];j--;}list[j + 1] = current;}}
🧪 算法演示
示例执行过程
输入数组: [49, 38, 99, 13, 49, 57]
📊 原始数组: 49, 38, 99, 13, 49, 57🔄 第 1 趟排序后: 38, 49, 99, 13, 49, 57
🔄 第 2 趟排序后: 38, 49, 99, 13, 49, 57
🔄 第 3 趟排序后: 38, 49, 空, 99, 49, 57
🔄 第 3 趟排序后: 38, 空, 49, 99, 49, 57
🔄 第 3 趟排序后: 空, 38, 49, 99, 49, 57
🔄 第 3 趟排序后: 13, 38, 49, 99, 49, 57
🔄 第 4 趟排序后: 13, 38, 49, 49, 99, 57
🔄 第 5 趟排序后: 13, 38, 49, 49, 57, 99✅ 排序后的数组: 13, 38, 49, 49, 57, 99
📝 实践
扩展思考题:
- 如何修改算法实现降序排序?
- 使用不同举例感受排序过程、稳定性(11,22,33,44,55或者55,44,33,22,11或者11,33,22,33,22等)?
- 在实际项目中,什么情况下会选择使用这种排序?
适用场景
场景 | 适用性 | 原因 |
---|---|---|
小规模数据 | 高 | 常数因子小,实际运行效率高 |
基本有序数据 | 高 | 接近最好情况O(n)的时间复杂度 |
链表结构 | 高 | 插入操作只需改变指针,无需移动元素 |
在线排序 | 高 | 可以动态插入新元素到已排序序列 |
大规模无序数据 | 低 | O(n²)的时间复杂度导致性能差 |