插入排序是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常是通过循环和比较来完成的。
基本思想
- 初始时,将第一个元素视为已排序。
- 取出下一个元素,在已排序元素序列中从后向前扫描。
- 如果该元素(已排序)大于新元素,将该元素移到下一位置。
- 重复步骤,直到找到已排序的元素小于或等于新元素的位置。
- 将新元素插入到该位置后。
- 重复步骤2-5,直到所有元素都排序完成。
算法步骤
- 从第二个元素开始,将其标记为
tmp
。 - 对于
tmp
元素,比较它与已排序部分的最后一个元素end
。 - 如果
tmp
小于已排序部分的元素,将已排序部分的元素向后移动一个位置。 - 重复步骤2和3,直到找到
tmp
应该插入的位置。 - 将
tmp
插入到这个位置。 - 重复步骤1-5,直到处理完所有的元素。
示例代码(从小到大排序)
void InsertSort(int* a,int n)
{
for (int i = 0; i < n - 1; i++)
{
int end = i;
int tmp = a[end + 1];
while (end >= 0)//end等于0则tmp比较到了第一个元素
{
if (tmp < a[end])
{
a[end + 1] = a[end];
end--;
}
else
{
break;
}
}
a[end + 1] = tmp;//找到插入位置并插入
}
}
时间复杂度
- 最好情况(已排序):O(n)
- 最坏情况(逆序):O(n^2)
- 平均情况:O(n^2)
稳定性
- 插入排序是稳定的排序算法,相同值的元素在排序后会保持原有的顺序。
空间复杂度
- 插入排序的空间复杂度为O(1),因为它是一个原地排序算法,不需要额外的存储空间。
优点
- 简单,易于实现。
- 对于小数据集非常有效。
- 稳定,不会改变相同元素的相对顺序。
- 自适应,如果输入数组已经是部分排序的,那么插入排序会跑得更快。
缺点
- 对于大数据集,效率较低。
- 平均和最坏情况下的时间复杂度较高。