直接插入排序算法
算法描述
直接插入排序(Straight Insertion Sort)是一种简单直观的排序算法。它的工作原理类似于我们整理扑克牌的方式:每次将一个新的元素插入到已经排好序的序列中的适当位置,直到所有元素都插入完毕。
算法步骤:
- 初始化:将第一个元素视为已排序序列
- 遍历:从第二个元素开始,逐个处理未排序元素
- 比较移动:将当前元素与已排序序列从后向前比较
- 插入:找到合适位置后插入当前元素
- 重复:直到所有元素都处理完毕
#include <stdio.h>
// 直接插入排序算法
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; i++) {
int key = arr[i]; // 当前要插入的元素
int j = i - 1;
// 将比key大的元素向后移动
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key; // 插入到正确位置
}
}
// 打印数组
void printArray(int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int arr[] = { 12, 11, 13, 5, 6 };
int n = sizeof(arr) / sizeof(arr[0]);
printf("排序前: ");
printArray(arr, n);
insertionSort(arr, n);
printf("排序后: ");
printArray(arr, n);
return 0;
}
执行过程示例:
初始序列: [12, 11, 13, 5, 6]
第1轮: 插入11 → [11, 12, 13, 5, 6]
第2轮: 插入13 → [11, 12, 13, 5, 6] (无需移动)
第3轮: 插入5 → [5, 11, 12, 13, 6]
第4轮: 插入6 → [5, 6, 11, 12, 13]
时间复杂度分析
1. 最坏情况 - O(n²)
- 情况:输入序列完全逆序
- 分析:每个元素都需要与所有已排序元素比较
- 计算:比较次数 = 1 + 2 + 3 + ... + (n-1) = n(n-1)/2 ≈ n²/2
2. 最好情况 - O(n)
- 情况:输入序列已经有序
- 分析:每个元素只需比较一次就能找到位置
- 计算:比较次数 = 1 + 1 + ... + 1 = n-1 ≈ n
3. 平均情况 - O(n²)
- 情况:随机排列的序列
- 分析:每个元素平均需要与一半的已排序元素比较
- 计算:比较次数 ≈ n²/4
时间复杂度总结:
情况 | 时间复杂度 | 说明 |
---|---|---|
最坏情况 | O(n²) | 序列完全逆序 |
最好情况 | O(n) | 序列已经有序 |
平均情况 | O(n²) | 随机序列 |
空间复杂度分析
空间复杂度 - O(1)
- 原因:算法只使用了常数级别的额外空间
- 具体分析:
- 只需要几个临时变量(key, i, j)
- 排序是原地进行的,不需要额外数组
- 不需要递归栈空间(迭代实现)
适用场景
适合使用:
- 小规模数据(n < 50)
- 基本有序的序列
- 作为其他算法的子过程(如快速排序的优化)
- 在线算法:数据逐个到达时需要实时排序
不适合使用:
- 大规模乱序数据
- 对性能要求很高的场景
优化方向
- 二分插入排序:使用二分查找找到插入位置,减少比较次数
- 希尔排序:通过分组插入排序来提高效率
- 使用哨兵:减少边界条件判断
直接插入排序虽然时间复杂度较高,但其实现简单、稳定、自适应等特点使其在特定场景下仍有实用价值。
评论区