插入排序
说到插入排序,想必大家都不陌生,这里简要的介绍一下。首先,它的思想是这样的,有一组数据,先取出第一个数,把它作为一个有序的数组。然后接着再取一个数,将它放到那个有序数组里的一个合适位置,使得这个数组仍然有序。如此循环下去,每次从原数组中取出一个数,放到有序的数组里。当所有数据都取完了,这个排序也就完成了。
用文字描述可能有些抽象,下面给出一个实例,例如对数组 {32,12,54,32,15} 进行排序。
首先将第一个元素,也就是32,看作是一个有序的序列。可以这样表示 {32|12,54,32,15} (里面那个竖线分割了有序序列和待排序的数组)
接下来,取待排序数组中的第一个元素,也就是12,因为它比32小,所以将它放到32的前面,于是有这样的表示 {12,32|54,32,15}。
基本过程就是这样,如此反复下去,知道待排序数组中的数据,都插入到有序序列的合适位置,排序就完成了。
对上面那个例子排序的全过程如下:
{32,12,54,32,15} => {32|12,54,32,15} => {12,32|54,32,15}
=>{12,32,54|32,15} => {12,32,32,54|15} => {12,15,32,32,54}
方法明白了,下面就给出代码,一个C语言升序排列的实现如下:
int i,j,tmp;
for(i = 1;i < len;i++){
j = i - 1;
tmp = arr[i];
while(j >= 0 && arr[j] > tmp){
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = tmp;
}
}
很容易看出来,这个算法有两层循环,插入排序的时间复杂度平均为O(n2),当问题规模越来越大的时候,插入排序的效率就会很低,所以插入排序之适用于问题规模较小的情况,至于n为多少才适用插入排序,在jdk源代码中有这样一段,应该可以作为一个参考。
这个是java.util.Arrays的sort()方法内部的代码。
* Sorts the specified sub-array of longs into ascending order.
*/
private static void sort1(long x[], int off, int len) {
// Insertion sort on smallest arrays
if (len < 7) {
for (int i=off; i<len+off; i++)
for (int j=i; j>off && x[j-1]>x[j]; j--)
swap(x, j, j-1);
return;
}
//其他部分省略
//
//
//
//
}
可以看到,在jdk中,只有长度小于7的数组才会应用插入排序,随着问题规模的增大,采用合并排序等算法,才是比较合适的。