算法学习之路(4)——插入排序与希尔排序

1、插入排序

  插入排序非常类似于整扑克牌。在开始摸牌时,左手是空的,牌面朝下放在桌上。接着,一次从桌上摸起一张牌,并将它插入到左手一把牌中的正确位置上。为了找到这张牌的正确位置,要将它与手中已有的牌从右到左地进行比较。无论什么时候,左手中的牌都是排好序的。

示例代码:

private static boolean less(Comparable v,Comparable w){
    return v.compareTo(w)<0;
}
    
private static void exchange(Comparable[] a,int i,int j){
    Comparable t = a[i];
    a[i] = a[j];
    a[j] = t;
}

/**
 * 插入排序
 * @param array
 */
public static void insertSort(Comparable[] array){
    int len = array.length;
    for(int i = 1;i<len;i++){
        for(int j = i;j>0 && less(array[j], array[j - 1]);j--){
            exchange(array,j,j-1);
        }
    }
}

  对于大规模乱序数组,插入排序的速度很慢,因为它只会交换相邻的元素,因此元素只能一点一点地从数组的一端移动到另一端。例如,如果主键最小的元素正好在数组的尽头,要将它挪到正确的位置就需要N-1次移动。

2、希尔排序

  希尔排序是简单改进了的插入排序,交换不相邻的元素以对数组的局部进行排序,并最终用插入排序将局部有序的数组排序。希尔排序的思想是使数组中任意间隔为h的元素都是有序的。排序示例:

                                         

实现希尔排序的方法是对于每个h,用插入排序将h个子数组独立地排序。因此,只需要在插入排序的代码中将移动元素的距离由1改为h即可。

代码示例:

/**
 * 希尔排序
 * @param array
 */
public static void shellSort(Comparable[] array){
    int len = array.length;
    int h = 1;
    while(h < len/3) h = 3*h + 1;
    while(h >= 1){
        for(int i = h;i<len;i++){
            for(int j = i;j>=h && less(array[j],array[j-h]);j-=h){
                exchange(array,j,j-h);
            }
        }
                h = h/3;
    }
}

注: 

while(h < len/3) h = 3*h + 1;

为选择初始的步长,读者也可以自定义步长。

原文地址:https://www.cnblogs.com/ljxxz/p/5462353.html