👦个人主页:Weraphael
✍🏻作者简介:目前正在学习c++和算法
✈️专栏:数据结构
🐋 希望大家多多支持,咱一起进步!😁
如果文章有啥瑕疵
希望大佬指点一二
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注😍
一、基本思想
基本思想:把待排序的元素从小到(从大到小)逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。
实际中,玩扑克牌时,整理一副牌从小到大或者从大到小就用到了插入排序的思想
二、算法原理
- 首先序列中的第一个元素(下标为0)是不需要排序的。因为当插入第一个元素时,序列中也没有元素与其比较,因此默认为有序。
- 当插入第
i
(i ≥ 1
)个元素时,由于要挪动数据,我们拿待插入元素
与当前数组内的最后一个元素(下标end)
进行比较,若a[i] < 数组最后一个元素
,则将当前元素向后移动一个单位,并将end--
继续向前比较,直到找到合适位置为止。
这里为大家举几个样例
- 插入
1
- 插入
3
- 插入
5
三、代码实现
以下代码以升序为例:
#include <stdio.h>
// n - 元素个数
void InsertSort(int* a, int n)
{
// 数组第一个元素不需要参与排序
// 下标从1开始
for (int i = 1; i < n; i++)
{
// end - 每一次数组最后一个元素的下标
// InsertNum - 要插入的元素
int end = i - 1;
int InsertNum = a[i];
while (end >= 0)
{
// 如果插入的元素比当前元素小,就要往后挪动数据
if (a[end] > InsertNum)
{
a[end + 1] = a[end];
end--;
}
// 插入比当前元素大,则直接插入
else
{
a[end + 1] = InsertNum;
break;
}
}
//当循环结束后,可能存在头插
if (end == -1)
{
a[end + 1] = InsertNum;
}
}
}
当然以上代码在插入过程中有重复代码,因此可以整合
#include <stdio.h>
// n - 元素个数
void InsertSort(int* a, int n)
{
// 数组第一个元素不需要参与排序
// 下标从1开始
for (int i = 1; i < n; i++)
{
// end - 每一次数组最后一个元素的下标
// InsertNum - 要插入的元素
int end = i - 1;
int InsertNum = a[i];
while (end >= 0)
{
// 如果插入的元素比当前元素小,就要往后挪动数据
if (a[end] > InsertNum)
{
a[end + 1] = a[end];
end--;
}
// 插入比当前元素大,则直接插入
else
{
break;
}
}
// 当循环结束后,存在两种情况
// 1. 头插
// 2. break跳出来的
// 以上情况直接插入即可
a[end + 1] = InsertNum;
}
}
【运行结果】
四、特性总结
- 时间复杂度
最好情况:原数组已经是按需求有序了,每趟只需与前面的有序元素序列的最后一个元素进行比较,总比较次数为n - 1
,时间复杂度为 O(N)
;
最坏情况:假设要排升序,原数组是逆序的情况下,O(N2)
综上,直接插入排序的时间复杂度为O(N2)
- 空间复杂度
O(1)
。只用到了一个数组
- 稳定性
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。如果碰见一个和插入元素相等的,那么将会把待插入元素放在相等元素的后面。所以,相等元素的相对的前后顺序没有改变,所以插入排序是 稳定 的。