排序算法-05希尔排序

希尔排序

1. 算法概述

是直接插入排序算法的一种更高效的改进版本,希尔排序是非稳定排序算法。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序

2. 算法原理

希尔排序的思想是使数组中任意间隔为h(步长)的元素是有序的。这样的数组也称为h有序数组,也即一个数组是h个互相独立的有序数组交叉编制在一起组成的数组。如图所示为一个h有序数组包含了4个有序子数组。

https://github.com/bye500/image/blob/master/%E7%AE%97%E6%B3%95/%E6%8E%92%E5%BA%8F/%E5%B8%8C%E5%B0%94/%E5%AD%90%E5%BA%8F%E5%88%97.png?raw=true

上图中,假设步长为4,则使 L-M-P-T,E-H-S-S,E-L-O-X,A-E-L-R为有序,然后将这4个数组交叉编制在一起组成一个大的数组:L-E-E-A-N-H-L-E-P-S-O-L-T-S-X-R,

排序过程:

  • 先取一个步长h1<arr.length(取值正整数),把所有序号相隔h1的数组元素放一组,组内进行直接插入排序
  • 然后在取一个步长h2<h1,重复上述分组和排序操作;
  • 直至hi=1,即所有记录放进一个组中排序为止
  • 实际就是arr[0]和arr[h]比较,arr[1]和arr[h+1]比较。。。每比较完一轮后,就缩小h的值
  • 该方法实质上是一种分组插入方法

希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。

3. 动图演示

下面动图以步长为arr.length/2为例,进行演示

4. 代码实现

 @Test
public void sort() {
    int[] arr = new int[]{49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 1};
    //设置步长,一般为数组(起始数组length >>> 1,分割数组length >>> 1 >>> 1...)长度一半
    int gap = arr.length >>> 1;
    //int gap = arr.length / x(设定步长);
    //根据步长,分割数组
    //for (; gap > 0; gap /= gap) {
    for (; gap > 0; gap >>>= 1) {
        //设置 第2个数组 起始索引 left = gap; 之后步长跨越为 left = left + gap * 循环次数
        for (int start = gap; start < arr.length; start += gap) {
            int temp = arr[start];
            //start - gap 为前一个 步长数组 相对位置的 元素
            int before = start - gap;

            boolean swap = false;
            //如果 前数据 > 后数据,则交换两者位置。依次,向前推,直至before <0 即表示该相对位置的元素已经有序
            for (; before >= 0 && arr[before] > temp; before = before - gap) {
                arr[before + gap] = arr[before];
                swap = true;
            }

            if (swap) {
                //最终 before + gap 位置会被空出,将临时元素填充进去
                arr[before + gap] = temp;
            }
        }
    }
    log.info("排序后:{}", JSON.toJSONString(arr));
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值