研究意义
直接插入排序是最基本的一种排序算法,其思想简单,容易掌握,对后期的学习也有一定的帮助。
必备知识(之后不再叙述)
排序:将一组杂乱无章的数据排列成一个按关键字有序的序列。
稳定性:关键值相同的记录,排序前后的相对次序不变。
排序前: 15 1 4 3 4
排序后: 1 3 4 4 15 稳定排序
1 3 4 4 15 不稳定排序
内排序与外排序:内排序是指记录集全部在内存中 ;外排序是指记录集部分在内存中,排序过程中,需访问外存 。
时间复杂度: 排序的时间复杂度可用算法执行中的数据比较次数与数据移动次数来衡量。后面一般都按平均情况进行估算。对于那些受对象关键字序列初始排列及对象个数影响较大的,需要按最好情况和最坏情况进行估算。
空间复杂度:排序过程中需要使用的辅助存储空间。
等差数列 前n项和公式:Sn=na1+n(n-1)d/2或Sn=n(a1+an)/2
主要内容:
一、算法思路(直接插入到已经有序的序列中)
设已存在一个有序子序列;每趟将一个记录按关键值大小插入到有序子序列中。初始化时,有序子序列只有一个记录。
直接插入排序就可以看作在一个只有一个元素的数组中插入数据,每一次插入都插入到合适位置。插入时前面的序列已经有序,让我们来模拟一下直接插入排序的方法。
假设我们拿到的数据是 5,7,3,8,2而手工排序的思路是 5 然后比较7和5的大小 ,合并为5,,7, 再在已经有序的5,7序列中插入3变为3,5,7,以此类推。
完整的排序思路 5,7,3,8,2 (初始状态)
5,7,3,8,2
3,5,7,8,2
3,5,7,8,2
2,3,5,7,8 (排序结束)
红色标记的数字为每一次需要排序的数字(需要插入的数字).
二、实现代码
#include <stdio.h>
#include <stdlib.h>
//直接插入排序
int main()
{
int a[10]={0,5,7,3,8,2,4,15,18,21};
int i=0,j=0,k=0;
printf("排序前的数据为:");
for(k=1;k<10;k++)
{
printf("%3d",a[k]);
}
printf("\n");
for(i=2;i<10;i++)
{
a[0]=a[i]; //a[0]为监视哨兵
for(j=i-1;a[0]<a[j];j--)
{
a[j+1]=a[j]; //数据移动移动
}
a[j+1]=a[0];//插入到正确位置
}
printf("排序后的数据为:");
for(k=1;k<10;k++)
{
printf("%3d",a[k]);
}
return 0;
}
注意:监视哨的作用:保存副本,避免数组下标越界。
三、算法分析
一个记录的辅助存储空间 —–监视哨
当问题规模为n时
最好情况(原本就是有序的)
比较次数:Cmin=n-1
移动次数:Mmin=0
最差情况(逆序)
比较次数:Cmax=1+2+3+4+……+n-1=(n-1)n/2
移动次数:Mmax=1+2+3+……+n-1=(n-1)n/2
若待排序对象序列中出现各种可能排列的概率相同,则可取上述最好情况和最坏情况的平均情况。在平均情况下的关键字比较次数和对象移动次数约为 n^2/4。因此,直接插入排序的时间复杂度为 o(n^2)。
另外直接插入排序是一种稳定的排序方法。