首页 > 编程语言 >排序算法之希尔排序

排序算法之希尔排序

时间:2023-04-23 10:33:03浏览次数:30  
标签:算法 cur 步长 插入排序 希尔 step 排序


希尔排序

1959年由唐纳德·希尔(Donald Shell)提出希尔排序。

希尔排序的思想:把数组中的元素看作是一个矩阵,分成m列,逐列进行排序(一般采用插入排序),m从某个整数逐渐减为1,当m为1时,整个序列将完全有序。因此,希尔排序也被称为递减增量排序(Diminishing Increment Sort)。

矩阵的列数取决于步长序列(step sequence),比如,如果步长序列为{1,5,19,41,109,…},就代表依次分成109列、41列、19列、5列、1列进行排序。不同的步长序列,执行效率也不同。

实例

希尔本人给出的步长序列是n/2^k(其中n为数组长度),例如要对下面的数组进行排序,n为16,步长序列是{1, 2, 4, 8}:

排序算法之希尔排序_java

首先分成8列进行排序:

排序算法之希尔排序_java_02

然后再分成4列进行排序:

排序算法之希尔排序_java_03

再分成2列进行排序:

排序算法之希尔排序_希尔排序_04

最后分成一列进行排序:

排序算法之希尔排序_希尔排序_05


最后数组中的元素就变成有序的了。

疑惑:直接分成一列进行排序不就行了,为什么要分成这么多列?不难看出来,从8列变为1列的过程中,逆序对的数量在逐渐减少,而希尔排序底层会使用插入排序,插入排序的时间复杂度与逆序对的数量成正比,这样就可以提高插入排序的效率。

因此希尔排序底层一般使用插入排序对每一列进行排序,也很多资料认为希尔排序是插入排序的改进版。

动图演示

排序算法之希尔排序_数据结构_06

代码实现

protected void sort() {

        List<Integer> stepSequence = shellStepSequence();
        
        for (Integer step : stepSequence) {
            sort(step);
        }

    }

    private void sort(Integer step) {

        // 对每一列进行插入排序
        for (int col = 0; col < step; col++) {

            // 插入排序
            for (int begin = col + step; begin < array.length; begin += step) {
                int cur = begin;
                E v = array[cur];
                while (cur > col && cmp(v, array[cur - step]) < 0) {
                    array[cur] = array[cur - step];
                    cur -= step;
                }
                array[cur] = v;
            }
        }
    }

    private List<Integer> shellStepSequence() {

        // n/2^k
        int n = array.length;
        List<Integer> list = new ArrayList<>();

        while ((n >>= 1) > 0) {
            list.add(n);
        }

        return list;
    }

复杂度与稳定性

最好情况是步长序列只有1,且序列几乎有序,时间复杂度为O(n)。

希尔本人给出的步长序列,最坏情况时间复杂度是 O(n^2)。

希尔排序的时间复杂度与步长序列有关。

更多精彩内容关注本人公众号:架构师升级之路

排序算法之希尔排序_希尔排序_07


标签:算法,cur,步长,插入排序,希尔,step,排序
From: https://blog.51cto.com/u_6784072/6216474

相关文章

  • Redis、Memcached、Guava、Ehcache中的算法
    1.LRU简单粗暴的Redis今天看 Redis3.0的发行通告里说,LRU算法大幅提升了,就翻开源码来八卦一下,结果哭笑不得,这旧版的"近似LRU"算法,实在太简单,太偷懒,太Redis了。在 Github的Redis项目里搜索lru,找到代码在redis.c的freeMemoryIfNeeded()函数里。先看 2.6版的代码:竟然就是随机找三......
  • 代码随想录算法训练营第四天 | 24.两两交换链表
     ......
  • m基于WDM网络的波长分配算法matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下:      2.算法涉及理论知识概要       波分复用WDM(WavelengthDivisionMultiplexing)是将两种或多种不同波长的光载波信号(携带各种信息)在发送端经复用器(亦称合波器,Multiplexer)汇合在一起,并耦合到光线路的同一......
  • #yyds干货盘点# LeetCode程序员面试金典:搜索旋转排序数组
    题目:整数数组nums按升序排列,数组中的值互不相同。在传递给函数之前,nums在预先未知的某个下标k(0<=k<nums.length)上进行了旋转,使数组变为[nums[k],nums[k+1],...,nums[n-1],nums[0],nums[1],...,nums[k-1]](下标从0开始计数)。例如,[0,1,2,4,5,6,7]在下标3处......
  • MATLAB图像倾斜校正算法实现:图像倾斜角检测及校正|附代码数据
    全文下载链接:http://tecdat.cn/?p=13981最近我们被客户要求撰写关于图像倾斜校正算法的研究报告,包括一些图形和统计输出。在本文中,随着多媒体技术的不断发展,数码相机,高清拍照手机等多媒体设备已经在人们的生活中占据了越来越重要的地位通过采用图像处理技术,可以将数码设备采集......
  • 算法学习day03链表part01-203、707、206--待办
    //这块需求重新进行学习packageLeetCode.linkedlistpart01;publicclassListNode{//结点的值intval;//下一个结点ListNodenext;//节点的构造函数(无参)publicListNode(){}//节点的构造函数(有一个参数)publicLis......
  • 视觉SLAM:模型介绍、算法框架及应用场景
    目录01 什么是SLAM 1.1 相机模型1.2 相机运动1.3建图02SLAM算法框架03SLAM的应用场景3.1自动驾驶的高精度定位3.2自主移动机器人知识扩展:组合导航(GNSS/INS)二维码导航/磁导航3.3室内场景的三维重建:AR(增强现实技术)等04 结语参考文献:本文主要想使用尽量少的专业词汇来解释......
  • 常见算法Python实现
    一、算法与数据结构1、二叉树1.重建二叉树输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如,输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建如下图所示的二叉树并输出它的头节......
  • C++的拓扑排序实现
    template<typenameT=CString,typename_Data=CString> structUnion_node//!<节点 { Union_node():nColor(0){} std::vector<Union_node*>vecNodeSon; Tkey;//!<关键数据 _Datadata;//!<卫星数据 mutableintnColor;//0:白色节点(未发现),1:灰色节点(发现),......
  • algorithm:算法库
    #include<algorithm>usingnamespacestd;//常用函数sort(begin,end);//对区间进行排序reverse(begin,end);//对区间进行翻转rotate(begin,middle,end);//将区间按照middle为界旋转unique(begin,end);//去除区间中相邻的重复元素min_element(begin,end);//找到......