基本思想
插入排序的思想如同它的名字一般:“插入”。
- 首先,我们可以将待排序的无序序列的首元素看作是一组有序序列a,序列元素个数为1,其后是一组无序序列b,元素个数为n-1。
- 每次取出无序序列的第一个元素b1,也即有序序列末尾元素的下一个元素。
- 将该元素b1从后往前,依次和有序序列中的元素ai比较。
- 被比较的有序元素ai如果大于该元素b1,有序元素ai向后移动一位,直到找到第一个小于该元素b1值(升序)的元素ak,将无序元素b1插入到该有序序列元素ak的下一个位置。
- 重复上面的过程,直到无序序列中没有元素,序列就被排序完成啦!是不是很简单呀?
算法流程
例如,有一个待排序的无序序列 {28,44,13,22,19,11,49,16,16,42 }
该序列通过插入排序得到有序序列的动画效果如下:
动画来源:算法可视化网站
看完这个动画,结合文章中对该算法的基本思想描述,能否自己写出插入排序的代码?
代码实现
- 语言:C++
- 序列存储结构:一维数组
在阅读这段代码之前,我先补充一个知识:数组初始化时,第0个位置不存放无序元素,该位置是用作插入排序的哨兵位置。引入哨兵的好处在于减少判断循环边界位置的比较次数,提高程序运行速度,话不多说,上代码:
/*
参数1:arr。一维数组的首地址
参数2:length。一维数组的元素个数(长度)
*/
void InsertSort(int* arr, int length)
{
for (int i = 2; i <= length; ++i)
{
//设置哨兵
arr[0] = arr[i];
int j = i - 1;
for (; arr[j] > arr[0]; --j)
{
arr[j + 1] = arr[j];
}
arr[j + 1] = arr[0];
}
}
总结
- 算法时间复杂度: O ( n 2 ) O(n^2) O(n2)
- 算法空间复杂度: O ( 1 ) O(1) O(1)
- 算法是否稳定:稳定
算法稳定指的是序列通过算法排序后,比较值相同(key)的两个元素相对顺序不会发生改变 - 算法适用范围:由于插入排序算法简单,高效,且具有稳定性,通常应用于序列元素较少的排序场合。