插入排序:
插入排序与选择排序一样,当前索引左边的所有元素都是有序的,但和选择排序不一样的是它们的位置不是固定的,可能为了更小的元素腾出空间,它们向后移动,但是当索引达到数组的右端时,数组排序就完成了
使用插入排序为一列数字进行排序的过程
具体算法描述如下:
- 从第一个元素开始,该元素可以认为已经被排序
- 取出下一个元素,在已经排序的元素序列中从后向前扫描
- 如果该元素(已排序)大于新元素,将该元素移到下一位置
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
- 将新元素插入到该位置后
- 重复步骤2~5
与选择排序的不同,插入排序所需的时间取决于输入元素的初始顺序,对一个很大且其中元素已经有序(或接近有序)的数组进行排序比随机顺序的数组或逆序的数组排序要快的多。
最坏的请款进行n^2/2次比较和N^2/2次交换,最好情况进行N-1次比较,0次交换
平均 n^2/4次比较和N^2/4次交换,所以插入排序的比较次数平均只有选择排序比较次数的一半
具体实现如下:
public static <T> void insertSort(Comparable<T>[] a){
// 将a[] 升序排列
int N = a.length;
for (int i = 1; i < N; i++) {//默认a[0]已经是有序的了,所以从a[1]开始检查
//检查新的元素是否比前面的元素小,只要小就交换,直到不小位置,由于前面的已经是有序的了,有一个不小,那前面的都不小
for(int j = i; j > 0 && less(a[j],a[j-1]);j--)
exch(a,j,j-1);//只要碰到小的就交换
}
}
测试程序如下
public class InsertionSort {
public static <T> void insertSort(Comparable<T>[] a){
// 将a[] 升序排列
int N = a.length;
for (int i = 1; i < N; i++) {
for(int j = i; j > 0 && less(a[j],a[j-1]);j--){
exch(a,j,j-1);
}
}
}
private static <T>boolean less(Comparable<T> v, Comparable<T> w){
return v.compareTo((T) w) < 0;
}
private static <T> void exch(Comparable<T>[] a, int i, int j){
Comparable<T> t = a[i];
a[i] = a[j];
a[j] = t;
}
private static <T> void show(Comparable<T>[] a){
//在单行中打印数组
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
public static <T> boolean isSorted(Comparable<T>[] a){
//测试数组元素是否有序
for (int i = 0; i < a.length; i++) {
if(less(a[i], a[i-1]))
return false;
}
return true;
}
public static void main(String[] args) throws FileNotFoundException {
// TODO Auto-generated method stub
// String[] a = {"S","O","R","T","E","X","A","M","P","L","E"};
Integer[] a = {-5,8,9,5,7,1,-68,1,5,33,100,563,526,16,21,68,-88};
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
insertSort(a);
assert isSorted(a);
show(a);
}
}