插入排序(Insertion Sort)的基本思想是将后一个记录插入到前面已经排好序的有序序列中,从而得到一个新的、记录数增1的有序序列。
最直观的栗子就是我们平时打斗地主,每次每人自己手动启一张牌,然后根据牌的大小,将刚启的牌插到手中的牌中。
1、直接插入排序
/*插入排序算法*/
void Insertion_Sort(int *arr, int len)
{
for (int i=2;i<=len;i++) /*手上单有一张牌时是不需要排序的,所以摸起第二张牌开始排序*/
{
int flag = 0; /*flag记录要插入的位置*/
if (arr[i-1] > arr[i]) { /*前一张牌大于后一张牌,要将后一张牌插入到前面的有序序列中*/
arr[0] = arr[i]; /*哨兵存储要插入的值,不然后移时会覆盖*/
/*往前找到比插入值小的位置,flag记录这位置的后一个*/
for (int j=i-1;arr[j]>arr[0] && j>0;flag=j,j--)
arr[j+1] = arr[j]; /*后移*/
arr[flag] = arr[0]; /*插入*/
}
}
}
我们需要先找到 i 和 i-1 的位置:
将要插入的值存储到哨兵处:
然后数据开始后移, j和 flag往前移:
遇到比插入值小数据,将插入值插入后一个位置:
在最好情况下,序列本身有序,那么没有移动次数,而比较次数显然显然为n-1次,时间复杂度为O(n)。
在最坏情况下,序列完全逆序,插入第2个元素时要考察前1个元素,插入第3个元素时要考虑前2个元素,插入第N个元素要考虑前 N-1个元素。因此,在最坏情况下的比较次数是 (n+2)(n-1)/2 次,移动次数是 (n+2)(n-1)/2 次,总的次数约等于n²+2n-3,所以在最坏情况下的复杂度为 O(
n²)
。
那么,插入排序的平均时间复杂度为O(n²/2)。
对于小规模数据,插入排序是一种非常快速的排序算法,且原理简单,结构紧凑。