系列文章目录
第一章 插入排序
前言
大家在玩扑克牌时,是否有这样一种情况,我们拿到一张牌时,总是会将这张牌按照从小到大的顺序放在指定的位置,比如我们现在手里有四张牌,分别是2 4 5 9,那么我们抽到第五张牌是3,于是,我们会将这张小瘪三与9比较,发现它比9小,按照道理应该放在9的前面,于是我们再与5比较,还是比5小,放在5的前面,依次类推,直到我们将这张3与2比较,发现它比2大,我们最终就确定了3这张牌在我们手上的位置,也就是放在2的后面。
这其实就是插入排序的一种基本思想,算是插入排序中的一轮,如果我们继续摸牌,然后按照上述做法,就完成了插入排序。
一、插入排序性质
1.时间复杂度O(n^2):插入排序最坏的情况下也就是整个序列逆序的情况,我们插入一个数就需要遍历一次,故最终结果时间复杂度为n的平方。
2.空间复杂度O(1):显然没有多占用其他空间,
3.我们发现序列越是接近有序,并且大的数在后面,小的数在前面,运行效率越高。
二、插入排序原理
1.情况一
比如我们有这么一组数字
我们将它们当作一组扑克牌来处理,假设我们第一次摸到一张三,然后我们现在去摸第二张牌,发现它是5,于是我们将这个5,与3比较,发现比3小,我们很随意的将它放在了3的后面,然后我们又摸了一张7,发现还是比5小,继续放5后面,然后摸了一张9,发现还是比7小,继续摸到一张3,这个时候的状态应该是这样。除了我们新摸到的牌之外,前面的牌应该都是有序的。
那我们现在的做法就是将这张新摸到的3与前面的比较,如果比3大,我们直接将被比较的数字往数组后面移动一个,这个时候要注意的是我们需要把这个新摸到的数提前保存,不然就会被9往后移动的时候覆盖,这里我们用end作为9的下标,tmp作为新数字3的下标,比较完成之后,end–,直到找到tmp应该在的位置。于是就有了
往后移动,把3覆盖,end前移,
继续与tmp比较,大于tmp的画要向后移动一次,然后end–
然后,tmp与5比较(未画出),5往后移。
最终得到的结果应该是tmp与3比较,不满足3大于tmp的条件,停止移动
此时我们只需要将tmp的值保存在end的后面即可。
这就是我们插入排序排一个数字所做的工作。
2.情况二
还有一种情况是我们将tmp与前面所有的数字比较,发现都比tmp大,这个时候end–已经小于0了,比如下面这样,蓝色框代表是空的没数据
这个时候,我们也是将tmp的放在end+1的位置即可。
二、插入排序实现
#include <stdio.h>
void PrintArr(int a[], int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
//插入排序,时间复杂度n^2
//最坏:逆序n^2
//最好:顺序n
void InsertSort(int a[], int n)
{
int i = 0;
for (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;//情况一,需要将tmp放在end+1的位置
}
}
//从while循环中自然退出的即为情况2
//从while循环中break的是情况1
//两种情况都需要执行相同的操作,即把tmp放在end+1的位置
//设计很巧妙,减少了代码量
a[end + 1] = tmp;
}
}
void TestInsertSort(int a[], int n)
{
InsertSort(a,n);
PrintArr(a, n);
}
int main()
{
int a[10] = { 1,2,2,6,6,7,5,5,6,0 };
TestInsertSort(a, 10);
return 0;
}
总结
这是直接插入排序的方法一种比较简答的排序方法,其思想和扑克牌排序的思想相同,实现起来也比较简单,是一种比较基础的排序方法。