前言
最近学习了排序算法,参考书籍《数据结构与算法分析-java版本》。总结一下,刷一下存在感,另外提高在csdn上的排名。
含义理解
本篇博客讲述“插入排序”,什么叫做“插入”呢?怎样解释,才能契合插入排序的实际真谛。我想,别人插你队的时候,应该更合适,所以“插入”等同与“插队”更合适。
实例讲解
假设有下面的一个数组:
{23, 2, 4, 6, 90, 0, 56}
23在第一个位置,因为它在第一个位子,无地方可插,所以它就不移动。
2是第二个位置,它前面有23,而且比自己大,所以要插23的队,所以23-2互换位置。数组如下:
{2, 23, 4, 6, 90, 0, 56}
现在我们看第三个位置上的4,发现它前面有23,且比自己大,所以要插队,23 - 4互换位置,4在第二个位置,它前面是2,2不小于4,所以不用换位置。
{2, 4, 23, 6, 90, 0, 56}
再看第4个位置,是数字6,它前面是23,所以要插队,23 - 6互换位置,换位置后,前面是4,不能再换位置。
{2, 4, 6, 23, 90, 0, 56}
再看位置5,是数字90,它前面是23, 23 小于 90,所以不用换位置。
然后是位置6,是0数字。因为0比90小,所以要换位置,另外0又比前面的23小,所以继续换位置,依次进行,0插入到最前面。
{0, 2, 4, 6, 23, 90, 56}
最后看位置7,是数字56,56 小于 90,所以56 插如到90前面,56 - 90 互换位置,56 前面是23,不用再换位置。因为此次已经是最后位置,所以排序结束。
{0, 2, 4, 6, 23, 56, 90}
我们可以看出,在位置N处,前面的数据都是有序的。后面的无序数据都是要插入到前面。
下面的gif,是本人在维基百科扣出来的,希望对理解有所帮助
代码实现
public void insertSor(int []array){
int length = array.length;
for(int i = 0; i< length; i++){//外层循环,挨个向后遍历
for (int j = i; j >0 ;j--){//内层循环,向前比对
if(array[j] < array[j-1]){//三值交换
int temp = array[j-1];
array[j-1] = array[j];
array[j] = temp;
} else {//如果不成立,早点退出循环
break;
}
}
}
}
因为三值交换比较耗时,这个地方可以优化:
public void insertSor(int []array){
int length = array.length;
for(int i = 0; i< length; i++){
int temp = array[i];
int j = i;
for (; j >0 && temp < array[j-1];j--){
array[j] = array[j-1];
}
array[j] = temp;
}
}
算法复杂度
明显的有2层循环,外层循环次数是N;内层循环是1+2+3+…+n-1+n;是一个等差数列。所以总循环次数:n(n+1)/2.
大O记法:O(n^2)
算法最坏情况是,数字已经是倒序排列:n(n+1)/2;没一个元素都要移动。
算法最好情况是,数字已经是正序排列:n;不需要走内层循环
总结
插入排序是其他高级排序的基础,比如希尔排序(shell sort)是在插入排序的基础上改进而来。所以掌握插入排序很有必要。