直接插入排序简介
什么是直接插入排序?
直接插入排序(Insertion Sort)是一种简单直观的排序算法。
其基本思想是什么?
把待排序的记录按其关键码值的⼤⼩逐个插 ⼊到⼀个已经排好序的有序序列中,直到所有的记录插⼊完为⽌,得到⼀个新的有序序列。
算法实现
算法一:
// 直接插入排序函数
void insertionSort(std::vector<int>& arr) {
int n = arr.size();
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 InsertSort(int* a, int b) {
fro(int i = 0; i < n - 1; i++) {
int end = i;
int tmp = a[end + 1];
while (end >= 0) {
if (a[end] > tmp) {
a[end + 1] = a[end];
end--;
}
else {
break;
}
}
}
}
算法原理
接下来我们就以算法一为例子为大家进行讲解。
函数定义和初始化:
void insertionSort(std::vector<int>& arr) {
int n = arr.size();
insertionSort 是一个函数,接受一个 std::vector<int> 类型的引用 arr 作为参数,目的是对这个数组进行排序。(vector在这里可以理解为动态数组)
int n = arr.size(); 获取数组 arr 的大小,后续会在循环中使用这个大小来遍历数组。
外层循环:
for (int i = 1; i < n; ++i) {
外层 for 循环从索引 1 开始,到 n - 1 结束。这意味着我们从数组的第二个元素开始,逐步将每个元素插入到已排序的子数组中。(索引范围1~n-1)
每次外层循环迭代,都假设 arr[0] 到 arr[i - 1] 已经是有序的,我们要将 arr[i] 插入到这个有序子数组的正确位置。
选择当前要插入的元素:
int key = arr[i];
int j = i - 1;
int key = arr[i]; 将当前要插入的元素 arr[i] 存储在变量 key 中。这样在后续比较和移动元素时,arr[i] 的值不会被覆盖。
int j = i - 1; 初始化一个变量 j,它指向当前要插入元素的前一个元素的索引。j 将用于在内层循环中遍历已排序的子数组。
内层循环(移动元素):
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
--j;
}
内层 while 循环用于将大于 key 的元素向后移动一个位置。只要 j 不小于 0 且 arr[j] 大于 key,就执行循环体。
在循环体中,arr[j + 1] = arr[j]; 将 arr[j] 向后移动一个位置,覆盖 arr[j + 1] 的原有值。--j; 将 j 减 1,继续向前检查前一个元素是否也大于 key,以便继续移动元素。
插入当前元素:
arr[j + 1] = key;
当内层 while 循环结束时,j 要么小于 0,要么 arr[j] 不大于 key。此时,j + 1 就是 key 应该插入的位置,将 key 插入到 arr[j + 1]。
算法实现过程:
第一轮外层循环,i = 1,将 arr[1] 插入到 arr[0] 之前(如果 arr[1] 小于 arr[0])或保持原位(如果 arr[1] 大于等于 arr[0])。
第二轮外层循环,i = 2,将 arr[2] 插入到由 arr[0] 和 arr[1] 组成的有序子数组的正确位置。
依此类推,直到所有元素都被插入到正确的位置,整个数组就完成了排序。
直接插⼊排序的优点
元素集合越接近有序,直接插⼊排序算法的时间效率越⾼
算法复杂度分析
1.时间复杂度:O(N^2)
2.空间复杂度:O(1)