排序-希尔排序

希尔排序

public class Shell {
    private Shell(){}
    public static void sort(Comparable[] a){
        int N = a.length;
        int h = 1;
        while (h<N/3) h =3*h + 1;
        while (h>=1){
            for(int i=h;i<N;i++){
                for(int j=i;j>=h&&less(a[j],a[j-h]);j-=h)
                    exch(a,j,j-h);
            }
            h/=3;
        }
    }
    private static boolean less(Comparable v,Comparable w){
        return v.compareTo(w)<0;
    }
    private static void exch(Comparable[] a,int vIndex,int wIndex){
        Comparable temp = a[vIndex];
        a[vIndex] = a[wIndex];
        a[wIndex] = temp;
    }
    private static void show(Comparable[] a){
        for(int i=0,len=a.length;i<len;i++)
            StdOut.print(a[i]+" ");
        StdOut.println();
    }
    private static boolean isSorted(Comparable[] a){
        for(int i=1,len=a.length;i<len;i++)
            if(less(a[i],a[i-1])) return false;
        return true;
    }
    public static void main(String[] args){
        String[] a = new In(args[0]).readAllStrings();
        sort(a);
        assert isSorted(a);
        show(a);
    }
}
实现策略

对大数组进行拆分变成较小的增量为h的数组,每个小的数组都是各自有序的,按照间隔递减的方式将小的元素尽量靠近左边,大的元素尽量靠近右边,交换方式采用插入排序方式,减少插入排序需要交换的次数。

分析

插入排序的问题:插入排序的性能问题主要体现在数组的规模和有序性问题。
希尔排序:希尔排序将插入排序的1增量改进为h增量,对间隔h的数组进行有序排列,优势在于减少了插入排序的交换次数(小的值都被移动到了靠近小值的一边,大的值都被移动到 了靠近大值的一遍)。原本需要一步一步移动的插入排序变为了大范围移动的插入排序。希尔排序的难点主要在于h的选择上,但是重要的是其运行时间肯定是小于平方级别的,对于一些简单 的中等排序,应该优先想到希尔排序。递增序列选用1 4 13…能满足大多数场景了,目前并没有找到一种很好的递增序列
在这里插入图片描述
如上图中的第一个S元素,本来是很大的元素,位置比较靠后,但是按照1 4 13…的递增序列使用希尔排序在第一次交换后就可将其放在它排序后所在位置,减少了最终增量为1的插入排序的交换次数。

动态图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值