插入排序是将数据插入到已经有序的序列中,类似扑克玩家整理手中牌的顺序:刚开始玩家只有一张牌,一张牌没有可比性,认为是有序的,然后玩家又抽出一张牌,假设将面值大的插到后面,他会从后向前寻找位置,当找到合适的位置时就将牌插进去。这就是插入排序的原理,假设给定一个组数:5,3,2,1,4,这组数的插入排序过程可用一张图表示,如下如:
记住,待插入的数据是从后向前寻找在已经排好序的序列中的位置的。所以可以得出以下算法描述:
insert_sort(array) for j=1 to array.length //数组下标从零开始 temp=array[j] //将temp插入到已经有序的序列中 i=j-1 while i>=0 && array[i]>temp array[i+1]=array[i]//比temp大的数向前移动 i=i-1 array[i+1]=temp//将temp插入到指定的位置
相应的Java代码实现如下:
static void insert_sort(int[] array){ int i=0,len=array.length; int temp=0,j=0; for(i=1;i<len;i++){ temp=array[i]; for(j=i-1;j>=0 && temp<array[j];j--){ array[j+1]=array[j]; } array[j+1]=temp; } }
算法分析:
因为每插入一个数,都要遍历有序序列,所以时间复杂度为:O^2,空间复杂度O(1)
优化策略:寻找插入位置时,利用折半查找法,可以加快查询时间,但是数据的移动次数还是不变,代码如下:
static void insert_sort(int[] array){ int i=0,len=array.length; int temp=0,j=0,pos=0; for(i=1;i<len;i++){ temp=array[i]; pos=finPos(array,temp,0,i);//找出插入位置 for(j=i-1;j>=pos;j--)//移动数据 array[j+1]=array[j]; array[pos]=temp; } } static int finPos(int[] array,int temp,int left,int right){ if(left<right){ int mid=(left+right)/2; if(temp>=array[mid]) return finPos(array,temp,mid+1,right); else return finPos(array,temp,left,mid); } return left; }