手撕面试题算法<排序>(3.5)—— 希尔排序

前言

之所以把希尔排序作为排序系列的第3.5篇,是因为希尔排序可以称得上是 插入排序Plus ,它在插入排序的基础上继续升级,突破了时间复杂度O(n2)的壁障

手撕算法 - 排序系列

手撕面试题算法<排序>(1)—— 冒泡排序及其优化实现
手撕面试题算法<排序>(2)—— 选择排序
手撕面试题算法<排序>(3)—— 插入排序及其优化实现
手撕面试题算法<排序>(3.5)—— 希尔排序
手撕面试题算法<排序>(4)—— 归并排序
手撕面试题算法<排序>(5)—— 快速排序以及快排为什么快
手撕面试题算法<排序>(6)—— 堆 & 堆排序
手撕面试题算法<排序>(7)—— 箱排序 & 基数排序

源码

看完有收获别忘了点个star哦~

希尔排序

思想

  • 希尔排序中,有一个叫做增量的概念,在排序过程中需要按照增量分组

  • 说白了,就是在一个数组中跳着选数组元素,归为一组,再将每个组进行直接插入排序

  • 在所有组的直接插入排序完成后,将增量按照一定的规则缩小,再将上述操作进行一遍,直到增量最终小于1

假如传入了一个大小为10的随机数组[7,3,4,1,8,9,2,0,6,5]

  • 让增量初始化为数组长度10,incr = 10
  • 排序开始,我们假定增量缩小的规则为每次让增量折半,即incr/=2,此时incr = 5
  • 我们将传入的一维数组看作n行5列的二维数组:
  • [7,3,4,1,8]
  • [9,2,0,6,5]
  • 此时,我们将每一列归为一组,按组分为:
  • [7,9]
  • [3,2]
  • [4,0]
  • [1,6]
  • [8,5]
  • 再将这些组中所有出现逆序的组进行插入排序
  • 一趟希尔排序完毕,将增量incr/=2,此时incr = 2
  • 重复以上操作直到incr<1

时间复杂度

希尔排序的时间复杂度取决于传入数组和增量策略的设置,一般来说,其时间复杂度范围在O(n*logn)~O(n2,平均时间复杂度为O(n1.5)

实现

    public static void sort(int[] arr) {
        int len = arr.length;
        int incr = len;
        while(incr>1){
            // 每趟希尔排序,都让增量的值折半
            incr/=2;
            for(int i=incr;i<len;++i){
                if(arr[i]<arr[i-incr]){
                	// 分组插入排序             	
            		// 当遍历时遇到相对有序,直接进行下一趟排序
                    for(int j=i;j>=incr && arr[j]<arr[j-incr];j-=incr){
                        Swaper.exec(arr,j,j-incr);
                    }
                }
            }
        }
    }

测试

排序测试:
在这里插入图片描述

由于希尔排序是时间性能突破了O(n2)的优秀排序算法,这次的测试用例数组直接上百万~

百万级数组耗时测试:

    int n = 1_000_000;
    int[] tmp = Tester.randomArr(n);
    int[] arr = tmp.clone();
    System.out.println("对有" + n + "个元素的随机数组进行排序:");
    long start = System.currentTimeMillis();
    sort(arr);
    long end = System.currentTimeMillis();
    System.out.println("希尔排序结束,耗时" + (end - start) + "ms");

结果:
在这里插入图片描述

是不是比之前那些O(n2)排序要快得多了~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值