经典排序算法之:希尔排序

1,原理及背景:

希尔排序算法是按其设计者希尔(Donald Shell)的名字命名,该算法由1959年公布,是插入排序的一种更高效的改进版本。它的做法不是每次一个元素挨一个元素的比较。而是初期选用大跨步(增量较大)间隔比较,使记录跳跃式接近它的排序位置;然后增量缩小;最后增量为 1 ,这样记录移动次数大大减少,提高了排序效率。希尔排序对增量序列的选择没有严格规定。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率
但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位

2,算法思想:

  • 基本思路:

先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量d2小于d1重复上述的分组和排序,直至所取的增量dt=1(dt 小于dt-l 小于… 小于 d2 小于 d1),即所有记录放在同一组中进行直接插入排序为止。该方法实质上是一种分组插入方法。

  • 可视轨迹:
    这里写图片描述

  • 性能分析:

希尔排序的时间复杂度与增量序列的选取有关,例如希尔增量时间复杂度为O(n^2),而Hibbard增量的希尔排序的时间复杂度为O(n^1.5),希尔排序时间复杂度的下界是n*log2n。希尔排序没有快速排序算法O(nlogn)快,因此中等大小规模表现良好,对规模非常大的数据排序不是最优选择,但是比O(n^2)复杂度的算法快得多。并且希尔排序非常容易实现,算法代码短而简单。 此外,希尔算法在最坏的情况下和平均情况下执行效率相差不是很多,与此同时快速排序在最坏的情况下执行的效率会非常差。专家们提倡,几乎任何排序工作在开始时都可以用希尔排序,若在实际使用中证明它不够快,再改成快速排序这样更高级的排序算法.

  • 实例程序:
public class Shell {
    //希尔排序:
    public static void sort(Comparable[] a){
        int n = a.length;
        int h = 1;
        while(h < n/3){
            h = 3*h+1;//1, 4, 13, 40, 121, ...
        }
        while(h >= 1){
            //将数组变为h有序(插入算法的变形):
            for(int i=h; h<n; i++){
                //将a[i]插入到a[i-h],a[i-2h],a[i-3h]...中
                for(int j=i; j>=h; j-=h){
                    if(less(a[j], a[j-h])){
                        exch(a,j,j-h);
                    }
                }
            }
        }
    }

    // v是否小于w ?
    private static boolean less(Comparable v, Comparable w) {
        return v.compareTo(w) < 0;
    }

    // 交换a[i]和a[j]
    private static void exch(Object[] a, int i, int j) {
        Object swap = a[i];
        a[i] = a[j];
        a[j] = swap;
    }

    // 打印数组到输出
    private static void show(Comparable[] a) {
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i]+" ");  
        }
        System.out.println();
    }

    //测试函数
    public static void main(String[] args) {
        Comparable[] a = new Comparable[]
                {'B','F','S','R','T','J','D','A','Z','V','Y','H','K','I','P','Q','C','G','N','U','M','E','O'};
        System.out.print("排序前:");
        show(a);
        System.out.print("排序后:");
        Selection.sort(a);
        show(a);
    }
}

[程序输出】:

排序前:B F S R T J D A Z V Y H K I P Q C G N U M E O 
排序后:A B C D E F G H I J K M N O P Q R S T U V Y Z 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值