详解十大经典排序算法(四):希尔排序(Shell Sort)

2023-12-05

算法原理

希尔排序是一种基于插入排序的排序算法,也被称为缩小增量排序。它通过将待排序的序列分割成若干个子序列,对每个子序列进行插入排序,然后逐步缩小增量,最终使整个序列有序。

算法描述

希尔排序(Shell Sort)是一种基于插入排序的算法,由Donald Shell于1959年提出。它是插入排序的一种更高效的改进版本。希尔排序的核心思想是将原始数据分成多个子序列,先对每个子序列进行插入排序,然后逐步减少子序列的数量,最终对整个数据序列进行插入排序。

这个算法的关键特点是其间隔序列的选择,即每次排序时元素之间的间隔。开始时,间隔较大,随着算法的进行,间隔逐渐减小,最后间隔为1,即普通的插入排序。通过这种方式,希尔排序可以快速减少大量的初期乱序,从而提高排序效率。

希尔排序的步骤如下:

  1. 选择合适的间隔序列 :最初的版本使用序列长度的一半作为第一个间隔,然后逐步减半,直到间隔为1。现代版本可能会使用不同的间隔序列。

  2. 分组并排序 :按照当前间隔将数组分为多个子序列,独立地对每个子序列应用插入排序。

  3. 减少间隔并重复 :减少间隔大小,重复上述过程,直到间隔减至1。

  4. 最终排序 :当间隔减至1时,进行一次标准的插入排序,此时由于序列已经部分排序,这一步骤会非常快。

动画演示

在这里插入图片描述

代码实现

public static void shellSort(int arr[]) {
        int n = arr.length;

        //设置排序的间隔(gap)。
        //初始间隔设置为数组长度的一半,每次循环后间隔减半。
        //循环继续直到间隔减至0。
        for (int gap = n / 2; gap > 0; gap /= 2) {

            //内层循环从gap开始,对数组进行遍历。
            for (int i = gap; i < n; i += 1) {
                int temp = arr[i];//存储当前元素的值。
                int j;//用于后续的内嵌循环,用于比较和交换元素。

                //此循环用于将较大的元素向右移动。
                //当j大于等于gap且arr[j - gap](当前元素的前一个间隔位置的元素)大于temp(当前元素)时,将arr[j - gap]向右移动到arr[j]的位置。
                for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
                    arr[j] = arr[j - gap];
                }
                //此处的j 是上面循环 j -= gap 后的。
                arr[j] = temp;
            }
        }


    }

算法复杂度

时间复杂度(最坏) 时间复杂度(最好) 时间复杂度(平均) 空间复杂度 稳定性
O(n^2) O(nlogn) O(n^1.5) O(1) 不稳定
  • 最好情况 :O(nlogn)
  • 平均情况 :取决于间隔序列。对于原始的间隔序列(减半序列),平均时间复杂度为O(n^1.5)。
  • 最坏情况 :取决于间隔序列。对于某些不佳的间隔序列,最坏情况可以达到O(n^2)。
  • 空间复杂度 :O(1)。希尔排序是一种原地排序算法。

希尔排序的优化方式

<<<前方高能 量力而行>>>

希尔排序的性能在很大程度上依赖于间隔序列的选择。不同的间隔序列会导致算法的性能有显著差异。优化希尔排序通常涉及使用更有效的间隔序列,而不是初始版本中的简单递减序列(如数组长度的一半递减至1)。以下是几种常见的优化方法:

  1. 优化间隔序列
  • Hibbard序列:使用形式为 2^k - 1 的间隔,如 1, 3, 7, 15, 31, … 这样的序列可以使希尔排序达到大约 O(n^(3/2)) 的时间复杂度。

  • Sedgewick序列:这是一种更复杂的间隔序列,可以进一步优化性能。一个常见的Sedgewick序列是 1, 5, 19, 41, 109, …

  • Knuth序列:使用形式为 (3^k - 1) / 2 的间隔,如 1, 4, 13, 40, 121, …

这些序列都是试图在排序过程中更有效地打乱数组,从而避免某些特定情况下的糟糕性能。

  1. 动态间隔

一种更高级的优化是根据数组的特定特征动态选择间隔。这种方法通常适用于特定类型的数据或在需要极致优化时使用。

下面是一个使用Hibbard间隔序列的希尔排序的Java实现示例:

 public static void sort(int[] arr) {
        int n = arr.length;
        int h = 1;

        // 计算最大间隔
        while ((h * 2) - 1 < n) {
            h = h * 2;
        }
        h = h - 1;

        // 希尔排序
        while (h >= 1) {
            for (int i = h; i < n; i++) {
                int temp = arr[i];
                int j;
                for (j = i; j >= h && arr[j - h] > temp; j -= h) {
                    arr[j] = arr[j - h];
                }
                arr[j] = temp;
            }
            h = (h + 1) / 2 - 1; // 更新间隔为下一个较小的Hibbard数
        }
    }

这段代码首先计算最大的Hibbard间隔,然后在每次迭代中减小间隔,直到间隔为1。每个间隔都会对数组进行一轮希尔排序。这种使用Hibbard间隔的方法通常比简单的递减间隔方法表现得更好。


相关概念
稳定 :如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
不稳定 :如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
时间复杂度 :对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
空间复杂度 :是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

详解十大经典排序算法(四):希尔排序(Shell Sort) 的相关文章

  • Java:获取当前正在执行的Method对应的对象

    将当前正在执行的方法作为 Method 对象获取的最优雅的方法是什么 我的第一个明显的方法是在辅助类中使用静态方法 该方法将加载当前线程堆栈 获取正确的堆栈跟踪元素 并根据其信息构造 Method 元素 有没有更优雅的方法来实现这一目标 这
  • 获取jdbc中表依赖顺序

    我在 MySQL 数据库中有一组表 A B C D 依赖关系如下 B gt C gt A 和 D gt A 也就是说 A 有一个 PrimaryKey C 有一个外键指向 A 的主键 B 有一个外键指向 C 的主键 类似地 D 有一个外键指
  • Java - 从配置文件加密/解密用户名和密码

    我们正忙于为客户开发 Java Web 服务 有两种可能的选择 将加密的用户名 密码存储在Web服务客户端上 从配置中读取 文件在客户端 解密并发送 将加密的用户名 密码存储在 Web 服务器上 从配置中读取 Web 服务器上的文件 解密并
  • 重构——套接字中的良好实践——简单的服务器-客户端 Swing 应用程序

    我使用单例和观察者模式编写了一个带有 Swing 接口的简单服务器 客户端程序 每个客户端都连接到服务器并可以发送消息 服务器将其收到的消息转发给其余的客户端 客户端使用 GUI 允许它们随时连接和断开与服务器的连接 该程序运行得很好 因为
  • 如何防止在 CXF Web 服务客户端中生成 JAXBElement

    我正在尝试使用 CXF 创建一个 Web 服务客户端来使用 WCF Web 服务 当我使用 wsdl2java 时 它生成具有 JAXBElement 类型而不是 String 的对象 我读到有关使用 jaxb bindings xml 文
  • H264 字节流到图像文件

    第一次来这里所以要温柔 我已经在给定的 H 264 字节流上工作了几个星期 一般注意事项 字节流不是来自文件 它是从外部源实时提供给我的 字节流使用 Android 的媒体编解码器进行编码 当将流写入扩展名为 H264的文件时 VLC能够正
  • Java中定义类型后同时初始化多个变量?

    这里需要一些语法方面的帮助 我正在尝试在定义类型后重新初始化多个变量 例如 int bonus sales x y 50 这工作正常 但是我想稍后在程序中将不同的值放入其中一些变量中 但我收到语法错误 bonus 25 x 38 sales
  • JBoss AS 5 中的共享库应该放在哪里?

    我是 Jboss 新手 但我有多个 Web 应用程序 每个应用程序都使用 spring hibernate 和其他开源库和 portlet 所以基本上现在每个 war 文件都包含这些 jar 文件 如何将这些 jar 移动到一个公共位置 以
  • JAX-WS:有状态 WS 在独立进程中失败

    我在 Tomcat 上部署了一个有状态的 Web 服务 它由工厂服务和主要 API 服务组成 并且工作得很好 工厂服务将 W3CEndpointReference 返回到主 API 实例 客户端使用会话 现在 我尝试将相同的服务作为独立应用
  • 中间件 API 的最佳实践是什么? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我们正在开发一个中间件 SDK 采用 C 和 Java 语言 供游戏开发人员 动画软件开发人员 阿凡达开
  • XSLT:我们可以使用abs值吗?

    我想知道在 XSLT 中我们是否可以使用 math abs 我在某处看到过这个 但它不起作用 我有类似的东西
  • NoSuchMethodError:将 Firebase 与应用程序引擎应用程序集成时

    我试图将 firebase 实时数据库与谷歌应用程序引擎应用程序集成 我在调用时收到此错误 gt DatabaseReference ref FirebaseDatabase gt getInstance gt getReference t
  • 如何列出所有可用的 LookAndFeel 主题?

    如何列出所有可用的 LookAndFeel 主题 我想在 JComboBox 中显示以供用户选择 这真的很简单 public static UIManager LookAndFeelInfo getInstalledLookAndFeels
  • Hibernate @OneToMany 注释到底是如何工作的?

    我对 Hibernate 还很陌生 我正在通过教程学习它 我在理解到底如何一对多注释作品 所以我有这两个实体类 Student代表一个学生并且Guide代表指导学生的人 因此 每个学生都与一名向导相关联 但一名向导可以跟随多个学生 我想要一
  • Jenkins 管道和 java.nio.file.* 方法的问题

    我正在尝试使用 java nio file 中的方法在 Jenkins 管道中执行一些基本文件操作 无论代码存在于哪个节点块中 代码都在主节点上执行 在管道中 我已经验证了各个节点块都是正确的 它们唯一地标识了特定的节点 但是 pathEx
  • 如何使用maven创建基于spring的可执行jar?

    我有一个基于 Maven 的 Spring WS 客户端项目 我想将其打包为单个 jar 在eclipse中 一切运行正常 当我尝试将其打包为可执行 jar 时 我收到 ClassNotFound 异常 因为 Spring jar 未包含在
  • JPA - 非主键字段上的 @OneToOne 关系不起作用

    我有一个 Spring Data JPA 后端 使用 Hibernate 作为 ORM 实现 这是模型 Person MailConfig id PK uid PK FK Person uid uid Entity
  • SWT - 与操作系统无关的获取等宽字体的方法

    SWT 有没有一种方法可以简单地获得跨各种操作系统的等宽字体 例如 这适用于 Linux 但不适用于 Windows Font mono new Font parent getDisplay Mono 10 SWT NONE 或者我是否需要
  • Java:基于 Web 的应用程序中的单例类实例

    我在 Web Application 中有这个 Singleton 类 public class MyDAO private static MyDAO instance private MyDAO public static MyDAO g
  • RecyclerView 不调用 onCreateViewHolder 或 onBindView

    没有收到任何错误 所有数据似乎都有效 由于某种原因 没有调用与视图相关的方法 我已确定以下事项 getItemCount 是唯一被调用的适配器方法 并且返回一个正整数值 我知道这将是你们将要查看的区域 构造函数正在被调用 成员变量有效 Pa

随机推荐

  • 文件搜索神器—Everything,结合内网穿透秒变在线搜索神器!

    Everything cpolar搭建在线资料库 实现随时随地访问 文章目录 Everything cpolar搭建在线资料库 实现随时随地访问 前言 1 软件安装完成后 打开Everything 2 登录cpolar官网 设置空白数据隧道
  • Latex正文引用图片编号,防止某张图片删除或调整导致正文序号对应错误

    一 背景 Latex真的是非常好用的论文排版工具 虽然不像word一样是 所见即所得 的可视化方式 但完全不用管格式 包括图片的排版 文字的缩进等等 这在word里调整起来真的是非常麻烦 特别是某个段落 图片修改后 又要重新调整格式 非常的
  • Ubuntu20.04安装向日葵、开机自启、解决windows系统远程黑屏(笔记)

    这里写目录标题 动机 1 Ubuntu20 04 安装向日葵 2 设置开机自启 3 解决windows不可远程的问题 4 大公告成 动机 办公室有个工作站 要比我的笔记本的CPU稍微好一点 用来跑陆面过程 我信心满满的装了个Ubuntu20
  • 什么是离岸公司?有什么作用?

    离岸公司是泛指在离岸法区内依据其离岸公司法规范成立的有限责任公司或股份有限公司 这些公司不能在注册地经营 而主要是在离岸法区以外的地方开展业务活动 离岸公司的主要特点包括高度保密性 无外汇管制和减免税务负担 离岸公司的作用主要有以下几个方面
  • 销售人员一定要知道的6种获取电话号码的方法

    对于销售来说 电话销售是必须要知道的销售方法 也是销售生涯中的必经之路 最开始我们并不清楚这么电话是从哪里来的 也不清楚是通过哪些方法渠道获取 那么今天就来分享给各位销售人员获取客户电话号码的方法 1 打印自己的名片 在工作当中少不了接触其
  • 5.【自动驾驶与机器人中的SLAM技术】2D点云的scan matching算法 和 检测退化场景的思路

    目录 1 基于优化的点到点 线的配准 2 对似然场图像进行插值 提高匹配精度 3 对二维激光点云中会对SLAM功能产生退化场景的检测 4 在诸如扫地机器人等这样基于2D激光雷达导航的机器人 如何处理悬空 低矮物体 5 也欢迎大家来我的读书号
  • 大Ⅲ周记11

    1 本周学习了mysql数据库操作的相关知识 根据课设要求完成了压降系统数据库表的设计 2 计算机网络完成了所有章节的作业 开始进入复习阶段 预计下周完成一至二章的复习作业
  • leetcode:93. 复原 IP 地址

    复原 IP 地址 中等 1 4K 相关企业 有效 IP 地址 正好由四个整数 每个整数位于 0 到 255 之间组成 且不能含有前导 0 整数之间用 分隔 例如 0 1 2 201 和 192 168 1 1 是 有效 IP 地址 但是 0
  • 最近在对接电商供应链,说说开放平台API接口

    B2B电商开放平台的设计需要从以下几面去思考 开放平台API接口 的接入 主要是从功能需求的角度 设计满足业务需求的接口及对应的字段 平台与商家之间信息的对接 对接的方法有哪些 对接过程中需要可能会遇到什么问题 同步开关及权限的设计 处理信
  • 鸿蒙4.0开发笔记之ArkTS装饰器语法基础@Prop@Link@State状态装饰器(十二)

    文章目录 一 哪些是状态装饰器 二 State Prop Link状态传递的核心规则 三 状态装饰器练习 一 哪些是状态装饰器 1 State 被装饰拥有其所属组件的状态 可以作为其子组件单向和双向同步的数据源 当其数值改变时 会引起相关组
  • Nessus简单介绍与安装

    1 Nessus简介 Nessus号称是世界上最流行的漏洞扫描程序 全世界有超过75000个组织在使用它 该工具提供完整的电脑漏洞扫描服务 并随时更新其漏洞数据库 Nessus不同于传统的漏洞扫描软件 Nessus可同时在本机或远端上遥控
  • WebGL笔记:矩阵平移的数学原理和实现

    矩阵平移的数学原理 让向量OA位移 x方向 tx y方向 ty z方向 tz 最终得到向量OB 矩阵平移的应用 再比如我要让顶点的x移动0 1 y移动0 2 z移动0 3 1 顶点着色器核心代码
  • 有效表达观点的艺术

    有效表达观点的艺术 在人际交往中 有效地表达自己的观点是建立良好关系和实现有效沟通的关键 然而 这并不总是易如反掌 有时候 我们可能会遇到表达困难 或者我们的观点可能被误解 本文将探讨如何有效地表达观点 以及掌握说话的艺术的重要性 首先 清
  • 人工智能:开启未来商业新篇章

    人工智能 开启未来商业新篇章 随着科技的快速发展 人工智能 AI 在商业领域的应用越来越广泛 成为企业把握未来商业机遇的重要方向 本文将探讨人工智能如何重塑商业格局 为企业提供新的增长点 以及企业如何抓住AI的商业契机 一 AI重塑商业格局
  • 机器人学英语

    我的prompt i want to you act as an english language teacher asistant to help me study english you could teach me in such a
  • 详解Hotspot的经典7种垃圾收集器原理特点与组合搭配

    详解Hotspot的经典7种垃圾收集器原理特点与组合搭配 HotSpot共有7种垃圾收集器 3个新生代垃圾收集器 3个老年代垃圾收集器 以及G1 一共构成7种可供选择的垃圾收集器组合 新生代与老年代垃圾收集器之间形成6种组合 每个新生代垃圾
  • 在深圳月入一万的很丢人吗

    在深圳 月入一万的收入是否丢人 这是一个很主观的问题 因为每个人的生活需求和价值观不同 从经济学的角度来看 深圳作为中国的经济特区和一线城市 其生活成本相对较高 从这个角度看 月入一万的收入在某种程度上可能不足以满足一些人的生活需求 根据最
  • 给自己泡了一壶茶

    清晨 当第一缕阳光透过窗户照亮了房间 我慵懒地爬起床 开始享受新的一天 我泡了一壶早茶 浅浅的茶香立刻弥漫在空气中 让我感到宁静而放松 我坐在窗边 静静地看着窗外的世界 清晨的街道上 行人和车辆都还不多 显得格外的宁静 微风吹过树叶 带来阵
  • 拍图识字软件哪个好用?这些好用的软件推荐给你们

    在快节奏的现代生活中 你可能会遇到需要从图片中获取文字信息的情况 无论是读书 工作还是生活中 有时候会需要从图片中提取文字 当你收到了一份手写的便签或菜单 上面的字迹可能很模糊 或者你需要在没有文字的地方快速获取信息 这时 你可能会想 如果
  • 详解十大经典排序算法(四):希尔排序(Shell Sort)

    算法原理 希尔排序是一种基于插入排序的排序算法 也被称为缩小增量排序 它通过将待排序的序列分割成若干个子序列 对每个子序列进行插入排序 然后逐步缩小增量 最终使整个序列有序 算法描述 希尔排序 Shell Sort 是一种基于插入排序的算法