高级排序:希尔排序

一.概述
希尔排序是插入排序的一种,又称“缩小增量排序”,是插入排序算法的一种更高效的改进版本。
在学习插入排序的时候,倒序将待排序的第一个数和前面已排序的数进行比较再往前插时,必须依次往前,效率较低。故可通过增加步长h来提高效率。

二.原理
1.选定一个增长量(步长)h,按照增长量h对数据进行分组;
2.对分好组的每一组数据为一轮,每一轮内进行插入排序;
3.按照规则减少增长量h,最后减为1,重复第二步操作

图1
如图,假设输入数组为{9,1,2,5,7,4,8,6,3,5} , 按照插入排序的思想,将数组分为已排序和未排序两部分。在插入排序中,当数组为初始状态时,将索引0处的数视为已排序,索引1到n-1为未排序部分。而在希尔排序中,索引为0的数依旧视为已排序,而由于未排序数字倒序向已排序数字进行比较时存在一个增长量(步长)h,所以初始状态时,索引h的数字为待排序数字。
第一轮:为了方便演示,令h的第一个值为5,即索引=5为最初的待排序数字也就是“4”。将4和与其距离h的已排序数比较,此时已排序数字为索引0处的“9” ,4<9,所以不进行插入。由于待排序数字每次倒序遍历时,要和已排序数字的距离为h的倍数,所以此时“4”只能和“9”比较。
第一个待排序数“4”比较结束,使用第二个待排序数字“8”向前遍历,数字“8”的索引为6,与其比较的数的索引为6-5=1,即数字“1”。1<8,不将8进行插入…同理进行后序排列。
第二轮,h为2,第一个待排序数字为索引=h=2的数,即“2”,2与索引为0的数“4”比较,2<4,所以2和4交换。…后面的同理

三.java代码实现

public class shell {
    public static void sort(int[] a) {
        int h = a.length / 2; //令初始h为数组长度的一半
        while (h >= 1) { //每一个不同的h 各视为一次完整的插入排序!
            for (int i = h; i < a.length; i++) { //第一轮为待排序第一个数字的范围,索引0视为已排序,所以从h开始
                for (int j = i; j >=h; j = j - h) { // j移动的步长为h,由普通插入排序的j--,变成j=j-h
                    if(a[j-h]>a[j]){
                        swap(a,j-1,j);
                    }else{
                        break;
                    }
                }
            }
        h=h/2;
        }
    }

    private static void swap(int[] a ,int i,int j){
        int x=a[i];
        a[i]=a[j];
        a[j]=x;
    }


    public static void main(String[] args) {
        int[] a = {4, 7, 6, 9, 2, 1};
        sort(a);
        System.out.println(Arrays.toString(a));
    }
}

测试结果:[1, 2, 4, 6, 7, 9]

需要注意的地方:

  1. 每一个不同的h 各视为一次完整的插入排序!
  2. 和基本的插入排序一样,外层循环i即待排序数,待排序数依次往后至最后一个数,所以i<a.length
  3. for内层循环时比较的是待排序数a[j-h]和a[j],所以j=i。每次跨越的步长为h,所以j=j-h。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值