目录
作者想说
介于网上的算法文章大多都是死板的文字,本人文字理解能力一直不强。决定花时间做图解,把困难的问题变简单,把抽象的思维变具体。给想学习程序的小伙伴更好理解的文章资源。
文学家的浪漫是把一切用文字来书写,程序员的浪漫是把我们心中所想用代码书写
这里我将用图解来书写,程序在我脑子里的样子,我叫@张三xy,致力于写出优质作品的编程爱好者
1.插入排序算法的简介
1.1.什么是插入排序
插入排序(InsertionSort),一般也被称为直接插入排序。
对于少量元素的排序,它是一个有效的算法。插入排序是一种简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增 1 的有序表
。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。
1.2.插入排序的算法性能
插入排序的平均时间复杂度也是 O(n^2),空间复杂度为常数阶 O(1),具体时间复杂度和数组的有序性也是有关联的。
2.插入排序算法的图解
2.1.第一轮排序
第一轮排序,我们从后往前找,发现 前面的值 > VAL 时,我们用前面的值覆盖了我们后面的值,然后在找到最左边时,我们把VAL插入到了我们刚刚找到的位置
2.2.第二轮排序
第二轮排序,我们从后往前找,发现 3 < VAL,此时的位置,我们的VAL 要放在 3 的后面
所以此时我们的位置已经确定,把 VAL 插入到 3 的后面,最终结果不变化
2.3.第三轮排序
第三轮排序,这一轮我们能够清晰的看到,我们的数组,整体向后移动的感觉,
注意,我们这次找到了最小值1,我们不断寻找,凡是比 VAL 小的我们都往后面移动一下,直到我们找到最顶端
因为比VAL大的都往后面移动了,此时VAL和它后面的 i 个值保持相对有序,有没有get到插入的感觉呢?
2.4.第四轮排序
第四轮排序,我们一样是先记录下VAL,然后不断往前找到属于它的位置,最后我们完成了这个排序的过程
3.插入排序算法的思考
3.1.插入排序为什么比选择和冒泡快一些?
答:
因为在计算机里,交换数据是很浪费时间的,我们减少了判断次数和交换次数,保持相对有序,自然而然就提升了排序速度和效率
3.2.插入排序的特点
答:
稳定相对顺序不会变,在序列基本有序的情况下,排序时间相对较快。会比我们的冒泡,选择快很多。最差的情况应该是将序列倒序变成顺序。
插入排序不仅不需要大量交换,而且我们比较次数也很少,我们用赋值覆盖的方式实现了这个数组往后移动,有了一个往前插入的效果
3.3.插入排序的最坏情况
答:
插入排序中,当待排序数组是有序时,是最优的情况,只需当前数跟前一个数比较一下就可以了,这时一共需要比较 N-1 次,时间复杂度为 O(N)。最坏的情况是待排序数组是逆序的,此时需要比较次数最多,最坏的情况是 O(n^2)。
而我们下一期要讲解的希尔排序完美的结合插入排序的优点,避开了缺点!
4.插入排序算法的代码实现
4.1.定义数组并传入到我们的插入排序函数
int main() {
//自定义一个数组演示
int len = 5; //数组长度
int a[] = {3,2,5,1,4};
//把数组 和 数组长度 传入到插入排序函数中
insertionSort(a,len);
return 0;
}
4.2.插入排序函数的实现
#include <stdio.h>
/**
* 插入排序
* @param a
* @param len
*/
void insertionSort(int a[],int len)
{
//从第二个数据开始
for(int i = 1;i < len;i++)
{
int val = a[i];//当前数据项
int idx = i - 1;//前一个数据的位置
//如果前一个数据项 >= 0,并且前一个数据项大于 当前数据项
while(idx >= 0 && a[idx] > val)
{
a[idx+1] = a[idx];
idx--;
}
//被插入的位置 和 i 的位置不一样,我们就进行插入操作(小优化)
if(idx + 1 != i)a[idx + 1] = val;
}
}