数据结构(邓俊辉)学习笔记】排序 7——希尔排序:Shell 序列 + 输入敏感性

news2024/12/28 3:02:12

文章目录

  • 1.邮资问题
  • 2. 定理K
  • 3.逆序对

1.邮资问题

此前曾经讲到希尔排序在对矩阵逐列排序时所使用的算法本身未必需要十分高效,而更重要的是应该具有输入敏感的特性,因此我们更倾向于使用插入排序。那么背后的具体原因又当如何解释呢?这里的核心依然是逆序队
在这里插入图片描述

让我们从所谓的邮资问题开始,假设在某个国家寄送一封平信需要5毛钱,而寄送一张明信片只需3毛5。进一步的,我们假设在这个国家所发行的邮票只有面值为4分以及1毛3的两种。那如果你需要邮寄一封平信或者明信片,你是否能够恰好用这两类邮票凑出所对应的邮资呢?稍作思考之后,我想你不难找出平信所对应的邮资方案。

是的,正如这幅图所画的那样,我们只需6张面额为4分的邮票,外加两张面额为一毛三的邮票,就恰好可以凑出平信所对应的邮资,也就是5毛钱。然而对于明信片,我想你会和我一样,无论如何苦思冥想也不能找出一种恰好的邮资方案。

如果你感兴趣,甚至可以编写几行简单的代码来穷举所有的可能,你将会发现:在这个国家的确无法贴出明信片所对应的邮资3毛5。由此我们可以看到,使用特定的一组邮票,对于有些邮资,我们可以恰好的凑出,而有些邮资无论如何都不能恰好的凑出,那么为什么会有这样的区别呢?

对于其他的邮资而言,我们又有什么样的一般性规律呢?翻译成数学的语言,我们可以说在这个国家用4分和1毛3面额的邮票所能凑出的邮资必然是4m 加上13n 的形式。这样一个有整数相乘,然后累加而形成的表达式,也称作线性组合 Linear combination。
在这里插入图片描述

当然我们也可以将以上的邮资问题推而广之,比如分别用 g 和 h 来代表两种邮票的面额,而用 m 和 n 分别代表这两类邮票所使用的数量。于是由 m 枚面额为 g 的邮票以及 n 枚面额为 h 邮票所共同构成的邮资,就可以表示为这样一个形式,也就是更一般意义上的 linear combination。

不难理解,通过线性组合我们的确可以凑出不同的邮资。但是正如我们已经看到的,有些邮资却总是无法凑出。实际上我们更加关注于后一类的邮资,对于面额特定的两枚邮票,我们不妨将所有不能由他们凑出的邮资汇成一个集合并记作 N(g,h)。

我们最为关注的是这个集合中的最大者,我们将其记作 X(g,h)。那么对于任何一对互素的 g 和 h,X 又是多少呢?

在此我们直接引述数论中的现成结论,数论告诉我们,X(g,h) 应该等于(g-1)*(h-1) - 1。当然你可以化简为很多别的形式,比如说 gh - g - h。

我不妨就刚才的实例来做一验证,也就是说在 g = 4,h = 13时,按照这个定理,x 应该等于4和13的乘积,再减去4和13的总和。不出意外,恰好就是35,也就是刚才明信片所对应的邮资。

当然,这个定理也告诉我们,从3毛6开始向上,所有的面额都是可以由这两种邮票凑出的。只要这两种邮票足够多。这样一个邮资的问题虽然有趣,但是它与我们这里的希尔排序又有什么关系呢?

2. 定理K

在这里插入图片描述

回到排序问题,我们首先来引入 h-sorting 以及 h-ordered 这两个概念。在某个序列中,如果任何一对距离为 h 的元素,都保持前小后大的次序,我们就称它为 h-ordered,也就是以 h 为间隔,是有序的。

当然作为其中的一个特例,在任何一个 one-ordered 的序列中,根据定义任何一对相邻的元素,彼此之间都是顺序的。应该记得我们在最初介绍起泡排序算法时就指出,某个序列中只要任何相邻的元素之间都是彼此顺序的,那么必然就是整体有序。所以我们说任何 one-ordered的序列,也必然是全局有序的。也就是我们排序算法最初需要输出的结果。

那么对于任何一个随机序列,如何使它变成是 h-ordered 的呢?

实际上如这幅图所示,我们只需采用希尔排序的那种方法,将输入的一维序列在逻辑上转换为一个宽度为 h 的矩阵,然后分别的逐列排序。你应该记得将整个序列在逻辑上转化为一个宽度为 h 的矩阵,并且逐列进行排序。在希尔排序中就称为 h-sorting。

由此我们可以做一简洁的归纳,也就是任何一个序列在做过 h-sorting 之后,必然是 h-ordered。
在这里插入图片描述

你应该记得在希尔排序中,每向前迭代一步,对应的矩阵宽度都会相应地减少。比如从前一轮的 g 减少为后一轮的 h。我们知道在经过前一轮的逐列排序之后,整个序列应该是 g-ordered。而在后一轮的逐列排序之后,这个序列也自然的应该是 h-ordered。那么在整个序列也达到以 h 为间隔有序的同时,此前以 g 为间隔的有序性是否能够依然得以延续呢?

这个问题的答案并不是那么一目了然。所幸的是 Knuth 已经在他那本著名的专注中给出了正面的答案。Knuth 指出:任何一个原先已是g-ordered 的序列在此后经过h-sorting 之后,依然保持是g-ordered。 也就是说相对于任何一个固定间隔而言的有序性,在希尔排序的过程中将会不断地保持并且持续地积累下来。

3.逆序对

在这里插入图片描述

现在还是回到我们的线性组合,考察我们的待排序列,如果它既是 g-ordered,同时也是 h-ordered。这样的序列也称作是 gh-ordered。实际上这样的序列也必然会以 g 和 h 之和为步长,是有序的。

我可以通过这个图来简明地证明这一点。在整个序列中考察任何一对相距 g + h 的元素,我们说它们必然是顺序的。因为我们可以找到,居于它们中间的这样一个特定的元素,这个元素到前一元素的距离为 g,而到后一元素的距离为 h。于是以这个中间元素为桥梁,根据不等式的单向传递性,我们自然就可以得知,这一对间隔为 g + h 的元素也必然是顺序的。

实际上这个结论也可以进一步地推广到 g 和 h 的任何一个线性组合。

我们仍然通过这组图来加以说明。在这序列中,我们考察任何一对间距为这个线性组合的元素。为了证明这一对元素之间的顺序性,我们无非是将刚才的方法推而广之,也就是说我们需要引入更多的中间桥梁。

比如这里给出的就是一种具体的方案,我们首先以 g 为间隔,连续地取出 m 个元素,在这些间隔位置上的所有元素必然是单调非降的。接下来我们再以 h 为间隔,连续地取出 n 个元素。同样的,这 n 个元素也必然是单调非降。于是通过所有这些单调不等号的串接,我们也就自然地证明了这样一对元素之间的顺序性。

由以上我们可以概括出一个结论:也就是凡是间距可以表示为线性组合的任何一对元素,必然是顺序的。简而言之,凡能表示为线性组合,则必然顺序。

在这里插入图片描述
现在我们将注意力集中于序列中秩为 i 的那个元素,如果 g 和 h 是互素的,而且整个序列已经是同时关于 g 和 h 有序的,那么相对于这个元素,哪些元素必然是顺序的?反过来哪些元素才有可能是逆序的?

我们说实际上可能逆序的元素不会很多,确切地讲无非就是刚才关于 g 和 h 的那个 x,也就是不能由 g 和 h 线性组合生成的最大的那个整数。

你能看出其中的原因吗?没错,对于这个区间之后的任何一个元素而言,它与 i 的距离已经超出了这个最大的阈值 x,所以它们之间的间隔也必然可以表示为 g 和 h 的线性组合。

而我们刚刚总结过,凡是能够表示为线性组合的,也就是顺序。反过来,i 这个元素所能参与构成的逆序对,只可能出现于这样一个范围(灰色区)。而随着希尔排序的不断迭代,这个范围也会不断地缩小。

没错,逆序列的总数会不断持续的减少。由此,你能想到点什么吗?没错,插入排序。我们知道插入排序具有输入敏感性,它的实际运行时间将线性正比于序列中所含逆序对的总数。

至此,我们终于弄明白了,为什么在希尔排序的底层,我们更加倾向于使用插入排序算法。实际上按照以上的优化思路,后人针对希尔排序曾经设计过许多更为优化的步长序列,比如 PS 序列、Pratt 以及 sedgewick 序列。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2116480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ubuntu16.04 vim使用中文出现乱编文档处理

问题现象 vim 编译文件时出现乱码问题 解决方法 1. 中文语言包安装: apt-get install language-pack-zh-hans 2. 配置环境变量:echo "export LC_ALLzh_CN.UTF-8" >>/etc/bash.bashrc 3. 修改当前环境的字符集 /etc/default/locale cat /etc/default/locale…

国内外网络安全政策动态(2024年8月)

▶︎ 1.《关于进一步加强智能网联汽车准入、召回及软件在线升级管理的通知》公开征求意见 8月1日,工业和信息化部装备工业一司联合市场监管总局质量发展局组织编制了《关于进一步加强智能网联汽车准入、召回及软件在线升级管理的通知(征求意见稿&#…

事务的原理

1. 什么是事务 事务就是一个包含多个步骤的事情,这些步骤要么都做好,要么都别做。 2. ACID 事务都跟ACID相关,注意这里说的是“相关”,而不是一定都“满足”。全都严格满足,是“刚性事务”,部分满足或一…

240908-Python代码实现6种与DBGPT-Knowledge-API的交互方式

A. Chat模式 # import asyncio # from dbgpt.core import ModelRequest # from dbgpt.model.proxy import OllamaLLMClient# clientOllamaLLMClient()# print(asyncio.run(client.generate(ModelRequest._build("qwen2:1.5b", "你是谁?"))))imp…

Debug-027-el-tooltip组件的使用及注意事项

前言: 这两天,碰到这个饿了么的el-tooltip比较多。这个组件使用起来也挺简单的,常用于展示鼠标 hover 时的提示信息。但是有一些小点需要注意。这里不再机械化的介绍文档,不熟悉的话可以先看一下: https://element-pl…

这个隐藏功能,90%的人还不知道!可一键直达40+AI应用!含Kimi、腾讯元宝、秘塔AI等常用AI工具

大家好,我是程序员X小鹿,前互联网大厂程序员,自由职业2年,也一名 AIGC 爱好者,持续分享更多前沿的「AI 工具」和「AI副业玩法」,欢迎一起交流~ 又是被粉丝感动的一天。 昨天一位读者加到我,是一…

基于Java+SpringBoot+Vue+MySQL的美容美发管理系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于SpringBootVue的美容美发管理系统【附源码文档】、前后…

音频创作无界限:全球热门剪辑软件深度评测

如果是一个音乐爱好者肯定会有过想要录制自己音乐作品的想法吧。这个操作放在早些年可能有些难度,但是现在是科技告诉发展的时代,互联网上有不少在线音频剪辑工具可以供我们选择。这次我们就一起来探讨有什么适合音频剪辑的工具。 1.福昕音频剪辑 链接…

3.C_数据结构_栈

概述 什么是栈: 栈又称堆栈,是限定在一段进行插入和删除操作的线性表。具有后进先出(LIFO)的特点。 相关名词: 栈顶:允许操作的一端栈底:不允许操作的一端空栈:没有元素的栈 栈的作用: 可…

【机器人工具箱Robotics Toolbox开发笔记(一)】Matlab机器人工具箱简介

MATLAB是一款被广泛应用于科学计算和工程领域的专业软件。它的全称为Matrix Laboratory(矩阵实验室),因为其最基本的数据类型就是矢量与矩阵,所以在处理数学和科学问题时非常方便,可用于线性代数计算、图形和动态仿真的…

系统架构的演进:同步通讯到异步通讯的过渡

系统架构的演进:同步通讯到异步通讯的过渡 一 . 同步通讯 VS 异步通讯1.1 同步调用方案① 耦合度高② 性能下降③ 资源浪费④ 级联失败 1.2 异步调用方案① 同步解耦② 性能提升 , 吞吐量增加③ 服务没有强依赖 , 不必考虑级联失败问题④ 流量削峰 1.3 小结 二 . 三…

【C++】STL学习——stack和queue的讲解(了解适配器)

目录 stack介绍queue介绍适配器stack的模拟实现queue模拟实现deque(了解) stack介绍 stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行 元素的插入与提取操作。stack是作为容器适配器被…

Java | Leetcode Java题解之第393题UTF-8编码验证

题目&#xff1a; 题解&#xff1a; class Solution {static final int MASK1 1 << 7;static final int MASK2 (1 << 7) (1 << 6);public boolean validUtf8(int[] data) {int m data.length;int index 0;while (index < m) {int num data[index];…

算法练习题18——leetcode240搜索二维矩阵||(二分)

题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 代码 class Solution {public boolean searchMatrix(int[][] matrix, int target) {for(int[…

双指针(6)_单调性_查找总价格为目标值的两个商品

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 双指针(6)_单调性_查找总价格为目标值的两个商品 收录于专栏【经典算法练习】 本专栏旨在分享学习C的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#…

DuPL: Dual Student with Trustworthy Progressive Learning for Robust WSSS

摘要 近年来&#xff0c;具有图像级标签的单阶段弱监督语义分割(WSSS)因其简化了其繁琐的多阶段语义分割而获得了越来越多的关注。由于类激活图(Class Activation Map, CAM)固有的模糊性&#xff0c;我们观察到一级管道经常会遇到由错误的CAM伪标签引起的确认偏差&#xff0c;…

基于SpringBoot的图书馆座位预约系统+小程序+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

继电器的使用

本文为大家讲一下继电器的常规使用. 添加 在菜单中选择 “绘制–无源元件–添加继电器(relay)” 以添加继电器. 或者用 shiftr(大写) 这个快捷键 继电器由一个线圈和该线圈所控制的铁质弹性开关(衔铁)组成. 原理 它的原理如下: 上面的铁质弹性开关, 默认情况下在弹力作用下…

java基础概念22-抽象类

一、抽象类的引入 1-1、封装 问题&#xff1a;javabean越来越多。重复的内容越多——继承 1-2、继承 二、抽象类、抽象方法 一个方法抽取到父类中&#xff0c;不确定方法体——抽象方法 定义了抽象方法的类——抽象类。 在Java中&#xff0c;抽象类是一种特殊的类&#xff0c…

博士生锻炼记录:2024.9.8

读博三年来感觉身体状况大不如前&#xff0c;虽然博士生的主要任务就是做课题和发文章&#xff0c;但是身体健康也是不容忽视的一环&#xff0c;一个好的身体是做好任何事情的基础&#xff0c;我们应该在不影响身体健康的前提下努力做课题。 这周初去参加了一个体成分测量的活…