插入排序是一个非常非常重要的排序算法,因为很多的应用场景都可以基于插入排序实现。
不过这里将的是普通插入排序的一种优化方案
普通的插入排序
public static int [] sort(int [] array){
for(int i=1;i<array.length;i++){ //拿第二个开始插入
int temp=array[i]; //
int pre=i-1; // 当前数字前一个开始遍历判断插入位置
while(pre>=0 && array[pre]>=temp){
array[pre+1]=array[pre]; //将比他大的元素往右挪动
pre--;
}
array[pre+1]=temp;
}
return array;
}
相当于,抽一张牌出来,然后将其后后面的元素一一比较,如果发现一个元素比改元素小,则将该元素前的所有元素向前移一位。然后将抽出来的牌置于空的地方。
这个方案是已经有一些优化了的,普遍的插入排序应该是一一比较并交换的过程
优化(加入二分查询)
因为插入排序的本质就是摸出一张新牌,然后找出这张牌需要插入的位置。
那么我们是不是可以用二分查找的办法来代替一张张牌遍历呢。
public static int serach(int [] array,int n,int index){
int left=0;
int right=index;
int mid;
while(left<right){
mid=(left+right)>>1;
if(array[mid]<=n){
left=mid+1;
}else {
right = mid ;
}
}
return right;
}
不同于二分查询,因为是需要查找插入牌的位置,而不是查找一个元素所在的位置。
所以可以进行判断 如果array【mid】 小于新抽的牌,那么 代表插入位置在左边。
当left==right的时候,会发现指向的位置就是插入的位置。
public static int [] sort2(int [] array){
for(int i=1;i<array.length;i++){ //拿第二个开始插入
int key=array[i];
int insert=serach(array,key,i);
for(int j=i ;j>insert;j--){
array[j]=array[j-1];
}
array[insert]=key;
}
return array;
}
所以得到了插入的位置的话就好办了,不需要一个个进行比较,只需要将插入下标之后的下标全部向后移一位就好了。
优点: 大大减少了数据比较过程