直接插入排序类似于我们平常在打扑克摸牌时候的一种情形。我习惯于左手拿牌右手摸牌,每次先把左手中的牌齐整齐,然后右手新摸一张牌中把它放到左手中正确的位置,让它成为一个新的整齐的牌堆。
如果根据上面的思路我们可以发现,直接插入排序的思想就是,从需要排序的第二个数字开始,拿取一个数,与前面的数字进行比较,放在合适的位置,使之成为一个新的有序数组。
直接插入排序c代码如下:
# include<stdio.h>
voidsort(int *a,int len){
int j,i,t;
for(j=1;j<len;j++){ //从第二个数字开始进行比较
if(a[j] < a[j-1]){ //如果当前的数字比原先已经排好的数组的最后一个数字还小的话,证明需要重新排序
t= a[j]; //把当前数字定义在一个临时变量中,方便后面的更改
for(i= j-1;a[i]>t && i >= 0;i--){ //判断条件,如果左边的数字比要插入的数字大的话,就交换两个数字。直到找到比它小的数字
a[i+1] = a[i];
}
a[i+1] = t; //把插入的数字放在特定的位置,让其成为一个新的有序数组
}
}
}
intmain(void){
int i;
int a[10] = {4,8,1,9,5,0,10,7,100,20};
sort(a,10);
for(i=0;i<10;i++){
printf("%d ",a[i]);
}
}
我们来看下插入排序的时间复杂度,我们这里先假设是最优的情况,比如有数组{1,2,3,4,5},本身就是已经排好序的了,那么比较次数为5-1=4,移动次数为0。所以可以推出原始的输入序列为正续的n个数组,那么它的比较次数为n-1,移动次数为0。这里我们再来看下最差情况,比如有数组{5,4,3,2,1},那么它的比较次数为1+2+3+4,移动次数为1+2+3+4+5-1,所以我们可以推出n个逆序数组的比较次数为n(n-1)/2,移动次数为n(n-1)/2+ n -1(注意多的n-1是因为每次需要发生移动的话,插入的数字本身也要移动)。如果是随机的情况下,根据概率论,我们可以推断出,移动次数和比较次数的平均约为n*n/4,所以直接插入排序算法的时间复杂度为n*n。
虽然直接插入排序的时间复杂度和冒泡排序和比较排序来说是一样的,但是直接插入排序的性能相对来说比上面的两种情况都要好点,建议在待随机排序的数据小于30个的时候,都使用插入排序。