排序算法 -- 插入排序
插入排序
插入排序的很像是打扑克的时候码牌的做法,我们在拿到分发到自己手里的牌后,一般会按照打牌的规则将纸牌依次排序,排序后的纸牌序列会给我们很多战术和战略的启发和帮助。插入排序的做法和我们将牌按序排列的做法十分相似。
首先我们考虑一个整数序列,这个序列里面的数字是无序的,就像是我们被分到一堆没有排列好的牌。我们怎么把他们排序呢?比如我们有一个无序的数组{3 , 7, 1, 4},首先我们拿到了3,我们认为一个元素的序列是有序的:
此时我们拿到下一个元素7,3与7比较,3在7的前面,所以将7插入3的后面。
然后我们拿到1,1依次与7和3比较,比现存的有序序列都小,则将1放在3的前面。
然后我们拿到4,4依次与7和3比较,比7小比3大,则将7放在3之间。
至此,整个排序完成。
按照这样的方法进行排序。在实现的时候我们引入一个哨兵位,一般会把哨兵位选择在数组的第0个位置,这样做的好处是:不会让比较向下越界,极限情况下最多比较N次,元素值比所有有序序列中的值小,将元素插入第1个位置;第二个好处是不需要额外的空间开销,在进行元素的后移时不需要进行元素的交换,每次都进行两次元素(交换a[guard] 和a[i]之间的元素交换、 a[guard] a[j+1]的元素交换)。
实现代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main() 5 { 6 int a[11]; 7 int guard=0; 8 9 int i = 2; 10 int j = 0; 11 12 /*Initialization*/ 13 for(i=0;i<=10;i++) 14 a[i] = 11-i; 15 /*Idears*/ 16 for(i=2;i<=10;i++) 17 { 18 a[guard] = a[i]; 19 20 for(j=i-1;j>0;j--) 21 { 22 if(a[j]>a[guard]) 23 { 24 a[j+1] = a[j]; 25 } 26 } 27 a[j+1] = a[guard]; 28 } 29 /*Output for Verification*/ 30 for(i=1;i<=10;i++) 31 printf("%4d",a[i]); 32 33 return 0; 34 }
如果目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况。最好情况就是,序列已经是升序排列了,在这种情况下,需要进行的比较操作需(n-1)次即可。最坏情况就是,序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。插入排序的赋值操作是比较操作的次数加上 (n-1)次。平均来说插入排序算法的时间复杂度为O(n^2)。因而,插入排序不适合对于数据量比较大的排序应用。但是,如果需要排序的数据量很小,例如,量级小于千,那么插入排序还是一个不错的选择。