1.引导
春节刚过不久,大家在春节闲来无事想必会呼朋唤友玩上几局惊险刺激的斗地主吧。其实在斗地主整理牌的过程中就是一个插入排序。大家细细琢磨一下,当摸牌时,第二张莫起来时,我们会与第一张牌比较,然后排序。莫第三张牌时,我们首先会很最右边的比较,如果小,我们又同右二牌比较,如果比右二大,我们就插在中间,如果小,我们就放在最左边。继续摸牌,继续这样比较,牌摸完了,也就整理完了。
2.特点
2.1 在上述斗地主整理牌的过程中,我们会发现,当我们摸下一张牌前,始终手上的牌是有序的。
2.2时间复杂度:
if我们每次摸牌时,摸到的牌都是比手中的牌大,那么每次排序就只需要比较与最右边的牌大小,也就是比较一次就行,所以时间复杂度为O(n).(正序)
else假如我们摸牌时,摸到的牌比最左边的牌还小,那么每次排序就需要比较手中牌有几张就有几次的次数,所以时间复杂度为O(n*n).(反序)
3.eg
4.代码展示
public static void inserrtSort(int[] arr){
if(arr==null||arr.length<2){
return;
}
for(int i=1;i<arr.length;i++){
for(int j=i-1;j>-1 && arr[j]>arr[j+1];j--){
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
外层for循环是摸牌的次数,内层for循环是摸牌后整理牌,排序的过程。
5.改进(二分插入排序)
大家仔细想一下我们摸牌的时候会从最右边一张一张的哈密哈眼的去比较吗???反正我是不会的,相信大家也不会。一般情况下摸牌起来的时候,我们会看一下摸上来的牌,然后从手上牌中间开始比较,这样比较的话,能快速 找到手中牌该插入的位置。所以二分插入排序出现了。
public static void erfenInsertSort(int[] arr){
for(int i=1;i<arr.length;i++){
int temp=arr[i]; //刚摸起来的牌
int low=0,high=i-1;
int mid=-1;
while(low<=high){
mid=low+(high-low)/2;
if(arr[mid]>temp){
high=mid-1;
}else{
low=mid+1;
}
}
for (int j=i-1;j>=low;j--){
arr[j+1]=arr[j];
}
arr[low]=temp;
}
}