Shell排序的原理与集体实现

SVN状态图标异常排查与修复指南 本文针对Windows系统中TortoiseSVN状态图标异常或消失的问题,提供了从易到难的完整排查与修复指南。核心原因是Windows资源管理器的状态图标显示位置有限,被其他软件占用。文章详细介绍了从客户端设置调整、识别并解决第三方软件冲突,到终极的注册表修改排序方案,帮助开发者高效恢复SVN状态图标,确保版本控制工作流的可视化与顺畅。 阅读详情

希尔排序因计算机科学家Donald L. Shell而得名,他在1959年发现了希尔排序算法。希尔排序基于插入排序,但是增加了一个新的特性,大大地提高了插入排序的执行效率。

       依靠这个特别的实现机制,希尔排序对于多达几千个数据项的,中等大小规模的数组排序表现良好。希尔排序不像快速排序和其它时间复杂度为O(N*logN)的排序算法那么快,因此对非常大的文件排序,它不是最优选择。但是,希尔排序比选择排序和插入排序这种时间复杂度为O(N2)的排序算法还是要快得多,并且它非常容易实现。它在最坏情况下的执行效率和在平均情况下的执行效率相比没有差很多。

插入排序:复制的次数太多

       由于希尔排序是基于插入排序的。回想一下在插入排序执行的一半的时候,标记符左边这部分数据项都是排过序的,而标记右边的数据项则没有排过序。这个算法取出标记符所指的数据项,把它存储在一个临时变量里。接着,从刚刚被移除的数据项的左边第一个单元开始,每次把有序数据项向右移动一个单元,直到存储在临时变量里的数据项能够有序回插。

       下面是插入排序带来的问题。假设一个很小的数据项在很靠近右端的位置上,这里本来应该是值比较大的数据项所在的位置。把这个小数据项移动到在左边的正确位置上,所有的中间数据项都必须向右移动一位。这个步骤对每一个数据项都执行了将近N次的复制。虽不是所有数据项都必须移动N个位置,但是数据项平均移动了N/2个位置,这就是执行了N次N/2个移位,总共是N2/2次复制。因此,插入排序的执行效率是O(N2)。

       如果能以某种方式不必一个一个地移动所有中间的数据项,就能把较小的数据项移动到左边,那么这个算法的执行效率就会有很大的改进。

N-增量排序

       希尔排序通过加大插入排序中元素之间的间隔,并在这些有间隔的元素中进行插入排序,从而使数据项能大跨度地移动。当这些数据项排过一趟序后,希尔排序算法减小数据项的间隔再进行排序,依此进行下去。进行这些排序时数据项之间的间隔被称为增量,并且习惯上用字母H来表示。

       现在有10个数据项,增量为4。在0、4和8号位置上的数据项已经有序了。

       当对0、4和8号数据项完成排序之后,算法向右移一步,对1、5和9号数据项进行排序。这个排序过程持续进行,直到所有的数据项都已经完成了4-增量排序,也就是说所有间隔为4的数据项之间都已经排列有序。

       在完成以4为增量的希尔排序之后,数组可以看成是由4个子数组组成:(0,4,8),(1,5,9),(2,6)和(3,7),这四个子数组内分别是完全有序的。这些子数组相互交错着排列,然而彼此独立。

       注意,在这个例子中,在完成以4为增量的希尔排序后,所有元素离它在最终有序序列中的位置相差都不到两个单元。这就是数组“基本有序”的含义,也正是希尔排序的奥秘所在。通过创建这种交错的内部有序的数据项集合,把完成排序所必需的工作量降到了最小。

       插入排序对基本有序的数组排序是非常有效的。如果插入排序只需要把数据项移动一位或者两位,那么算法大概需要O(N)时间。这样,当数组完成4-增量排序之后,可以进行普通的插入排序,即1-增量排序。4-增量排序和1-增量排序结合起来应用,比前面不执行4-增量排序而仅仅应用普通的插入排序要快得多。

减小间隔

       上面已经演示了以4为初始间隔对包含10个数据项的数组进行排序的情况。对于更大的数组开始的间隔也应该更大。然后间隔不断减小,直到间隔变成1。

       举例来说,含有1000个数据项的数组可能先以364为增量,然后以121为增量,以40为增量,以13为增量,以4为增量,最后以 1为增量进行希尔排序。用来形成间隔的数列被称为间隔序列。这里所表示的间隔序列由Knuth提出,此序列是很常用的。数列以逆向形式从1开始,通过递归表达式

       h=3*b+1

       来产生,初始值为1。

       还有一些其他的方法也能产生间隔序列;后面会讲到这个问题。首先,来研究使用Kunth序列进行希尔排序的情况。

       在排序算法中,首先在一个短小的循环中使用序列的生成公式来计算出最初的间隔。h值最初被赋为1,然后应用公式h=3*h+1生成序列1,4,13,40,121,364,等等。当间隔大于数组大小的时候,这个过程停止。对于一个含有1000个数据项的数组,序列的第七个数字,1093就太大了。因此,使用序列的第六个数字作为最大的数字来开始这个排序过程,作364-增量排序。然后,每完成一次排序全程的外部循环,用前面提供的此公式倒推式来减小间隔:

       h=(h-1)/3

       这个倒推的公式生成逆置的序列364,121,40,13,4,1。从364开始,以每一个数字作为增量进行排序。当数组用1-增量排序后,算法结束。

       希尔排序比插入排序快很多,它是基于什么原因呢?当h值大的时候,数据项每一趟排序需要移动元素的个数很少,但数据项移动的距离很长。这是非常有效率的。当h减小时,每一趟排序需要移动的元素的个数增多,但是此时数据项已经接近于它们排序后最终的位置,这对于插入排序可以更有效率。正是这两种情况的结合才使希尔排序效率那么高。

       注意后期的排序过程不撤销前期排序所做的工作。例如,已经完成了以40-增量的排序的数组,在经过以13-增量的排序后仍然保持了以40-增量的排序的结果。如果不是这样的话,希尔排序就无法实现排序的目的。

希尔排序的Java代码

class ArraySh{

    private long[] theArray;

    private int nElems;

    public ArraySh(int max){

       theArray=new long[max];

       nElems=0;

    }

    public void insert(long value){

       theArray[nElems]=value;

       nElems++;

    }

    public void display(){

       System.out.print("A=");

       for(int j=0;j<nElems;j++)

           System.out.print(theArray[j]+" ");

       System.out.println("");

    }

    public void shellSort(){

       int inner,outer;

       long temp;

      

       int h=1;

       while(h<=nElems/3)

           h=h*3+1;

       while(h>0){

           for(outer=h;outer<nElems;outer++){

              temp=theArray[outer];

              inner=outer;

             

              while(inner>h-1 && theArray[inner-h]>=temp){

                  theArray[inner]=theArray[inner-h];

                  inner-=h;

              }

              theArray[inner]=temp;

           }

           h=(h-1)/3;

       }

    }

}

其他间隔序列

       选择间隔序列可以称得上是一种魔法。至此只讨论了用公式h=h*3+1生成间隔序列,但是应用其他间隔序列也取得了不同程序的成功,只是一个绝对的条件,就是逐渐减小的间隔最后一定要等于1,因此最后一趟排序是一次普通的插入排序。

       在希尔的原稿中,他建议初始的间距为N/2,简单地把每一趟排序分成了两半。因此,对于N=100的数组逐渐减小的间隔序列为50,25,12,6,3,1。这个方法的好处是不需要在不开始排序前为找到初始的间隔而计算序列;而只需要用2整除N。但是,这被证明并不是最好的数列。尽管对于大多数的数据来说这个方法还是比插入排序效果好,但是这种方法有时会使运行时间降到O(N2),这并不比插入排序的效率更高。

       这个方法的一个变形是用2.2而非2来整除每一个间隔。对于N=100的数组来说,会产生序列45,20,9,4,1。这比用2整除显著改善了效果,因为这样避免了某些导致时间复杂度为O(N2)的最坏情况的发生。不论N为何值,都需要一些额外的代码来保证序列的最后取值为1。这产生了和清单中所列的Knuth序列差不多的结果。

       递减数列的另一个可能是

if(h<5)

    h=1;

else

    h=(5*h-1)/11;

       间隔序列中的数字互质通常被认为很重要:也就是说,除了1之外它们没有公约数。这个约束条件使每一趟排序更有可能保持前一趟排序已排好的效果。希尔最初以N/2为间隔的低效性就是归咎于它没有遵守这个准则。

       或许还可以设计出像如上讲述的间隔序列一样好的间隔序列。但是不管这个间隔序列是什么,都应该能够快速地计算,而不会降低算法的执行速度。

希尔排序的效率

       迄今为止,除了在一些特殊的情况下,还没有人能够从理论上分析希尔排序的效率。有各种各样基于试验的评估,估计它的时间级从O(N3/2)到O(N7/6)。

Ubuntu系统用户查看与审计实战:从passwd到可交付清单 Linux系统用户是权限管理的基础概念,其核心存储于/etc/passwd文件,遵循UID/GID、登录Shell、主目录等标准化字段结构。理解该机制的原理,有助于识别可交互登录用户、系统服务账户及潜在安全风险账户。技术价值在于支撑安全巡检、合规审计与运维自动化,典型应用场景包括服务器加固、LPIC/RHCSA备考、中小团队基线核查。本文聚焦Ubuntu发行版,深度解析getent、awk、id与shadow协同验证方法,覆盖UID范围划分、nologin/false Shell判别、密码锁定状态(*与!) 阅读详情

相关推荐

Android SwipeRefreshLayout 原理与高可用实践指南

SwipeRefreshLayout 是 Android 中实现下拉刷新的标准控件,其本质是一个基于事件拦截与 ValueAnimator 驱动的 ViewGroup,通过封装手势识别、滚动状态判断和 Material 规范动画,为开发者提供开箱即用的刷新体验。它依赖 canChildScrollUp() 判断是否触发刷新,内部通过 mTarget 机制协调子 View 滚动行为,在 RecyclerView、NestedScrollView 等场景中需特别注意嵌套滚动兼容性。其技术价值在于极低的接入成本、

weixin_34195546的博客 370

排序算法 | 希尔shell排序,算法的图解、实现、复杂度和稳定性分析

1、希尔排序——定义 希尔排序按其设计者希尔(Donald Shell)的名字命名,该算法由希尔 1959 年公布。 希尔排序是基于插入排序的以下两点性质而提出改进方法的: 1、插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。 2、但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。 2、希尔排序——步骤描述 3、希尔排序——算法实现 4、希尔排序——复杂度、稳定性分析 由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序, 但在不同的插入排

比特的一天 4825

SVN状态图标消失终极指南:从缓存设置到注册表调试(避坑版)

本文深入解析Windows系统中SVN状态图标(如绿色小钩图标)消失的常见原因,并提供从调整状态缓存设置到修改注册表排序的完整修复方案。文章对比了两种方法的适用场景与风险,并特别针对Windows 11系统提供了高级排查指南,帮助用户彻底解决图标叠加失效问题,恢复高效的文件状态识别体验。

docker7nomad的博客 783

八大排序算法——希尔(shell)排序(动图演示 思路分析 实例代码java 复杂度分析)

一、动图演示 二、思路分析 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。   简单插入排序很循规蹈矩,不管数组分布是怎么样的,依然一步一步的对元素进行比较,移动,插入,比如[5,4,3,2,1,0]这种倒序序列,数组末端的0要回到首位置很是费劲,比较和移动元素均需n-1次。   而希尔排序在数组中采用跳跃式分组的策略,通过某个增量将数组元素划分为若干组,然后分组..

qq_36098514的博客 1033

Shell脚本实现乱序排列文件内容的多种方法(洗牌问题)

主要介绍了Shell脚本实现乱序排列文件内容的多种方法(洗牌问题),本文给出3个Shell脚本和一个Python脚本解决乱序排列文件内容问题,需要的朋友可以参考下

卷积神经网络-猫狗识别(附源码)

利用python实现一个卷积神经网络,训练猫狗数据集,实现对猫狗图片的预测识别

m0_63223213的博客 2万+

插入排序与Shell排序(图解+代码实例)

插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。 1、直接插入排序(Insertion Sort) 基本思想:每一次排序将一个待排序的数据,按其关键字的大小插入到前面的已经有序的序列中,然后进行排序,使其包含插入数据的序列再次有序,重复上述操作,直至整个序列有序,排序结束。 一般情况下其时间复杂度为O(n^2),当所排序列本身有序时,其时间复杂度为O(n),空间复杂度为O(1)。 这个排序算法是稳定的。 ...

hyz529900的博客 1627

保姆级教程:用YOLOv5s训练PCB缺陷检测模型(附北大公开数据集)

本文提供了一份基于YOLOv5s的PCB缺陷检测模型从零开始的完整实战教程。详细解析了如何使用北大公开数据集,涵盖环境搭建、数据处理、模型训练、性能评估及优化部署全流程,并针对工业场景中常见的类别不均衡问题给出了具体解决方案,旨在帮助开发者快速构建高精度的自动化质检系统。

weixin_28285943的博客 306

shell的排序

shell的排序

m0_71931851的博客 2173

Qemu开发ARM篇-3、qemu运行uboot演示

在上一篇文章中,我们搭建了交叉编译工具链,并成功进行了uboot的交叉编译,在该篇中,我们将演示如何利用qemu运行上一篇中交叉编译的uboot程序。

sinat_33909696的博客 1210

电子电气架构 --- 整车电源管理

保证启动能力:防止因电池电量耗尽而导致的车辆无法启动,这对于确保车辆在任何时候都能可靠运行至关重要。 延长电池寿命:通过避免电池深度放电,有助于延长其使用寿命,减少更换电池的需求和成本。 提升用户体验:虽然负载被关闭可能会暂时影响舒适度,但通过在必要时自动采取行动,可以减少驾驶员的焦虑和不确定性,提高整体的用户满意度。

Soly_kun的博客 1083

排序算法--希尔排序(ShellSort)的原理、排序思路、适用场景及代码示例

希尔排序(ShellSort) 概念介绍 希尔排序(ShellSort): 是插入排序的变种,又称缩小增量排序(Diminishing Increment Sort), 是直接插入排序算法的一种更高效的改进版本。 希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。 希尔排序是基于插入排序的以下两点性质而提出改进方法的,通过减少了其复制的次数,提高排序效率 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。 但插入排序一般来说是低效的,因为插入排序

penriver的博客 3552

AI Agent开发第85课-DeepSeek-OCR 安装全指南:从 Transformers 到 vLLM,手把手教你跑通企业级 OCR

本文系统讲解 DeepSeek-OCR 的两种部署方式——基于 Hugging Face Transformers 的标准推理与基于 vLLM 的高性能加速推理。详细说明 CUDA 与 PyTorch 版本匹配、环境验证、依赖安装等关键细节,并提供可直接运行的完整代码示例。无论你是单卡调试还是高并发服务部署,都能在这里找到清晰路径。

打造全国最全的AI Agent开发知识领域的博客 2540

基本排序(二)插入排序(直接插入、Shell、折半)

  插入排序是常见的内部排序之一。常见的插入排序包括直接插入排序、Shell排序、折半排序。本篇主要介绍这三个排序。   转载请注明出处——http://www.cnblogs.com/zrtqsk/p/3807611.html,谢谢! 一、直接插入排序   直接插入排序大概是我们最容易理解的一类排序了。   1、原理   对于n个元素的记录。   第一趟  :  把第2个元素拿...

weixin_34192816的博客 233

【WRF理论第十四期】 VEGPARM.TBL 文件详解

WRF 读取 VEGPARM.TBL 文件

WW、forever的博客 575

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

【插入排序】:直接插入排序、二分插入排序、shell排序

【代码】【插入排序】:直接插入排序、二分插入排序、shell排序。

2401_82641862的博客 550

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

CLI复兴:大厂为何集体拥抱命令行工具?

命令行界面(CLI)作为用户与计算机系统交互的基础方式,其核心原理在于通过文本指令直接调用系统功能,避免了图形界面(GUI)的渲染开销与交互延迟。从技术价值看,CLI天然具备可编程性与脚本化能力,能够无缝融入自动化流程,成为DevOps实践中基础设施即代码(IaC)的关键载体。在应用场景上,CLI凭借其轻量级、低开销的特性,在远程服务器管理、容器化环境(如Docker、Kubernetes)以及持续集成/持续部署(CI/CD)流水线中发挥着不可替代的作用。随着云原生和自动化需求的爆发,各大科技公司纷纷强化C

weixin_30800987的博客 341

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

shell编程之大数据面试题

1、linux常用高级命令 1.1、top --实时查看内存 1)第一行 23:07:25 : 当前系统时间; user : 用户个数; load average : 三个数分别表示1分钟,五分钟,15分钟的负载状况 ***高于5表明系统在超负荷运转 2)第二行 task:任务(进程) –系统共有250个进程,1个在运行,249在休眠,0个stop,0个僵尸状态 3)CPU状态 us:用户空间占用CPU的百分比 sy:内核空间占用CPU的百分比 ni:改变过优先级的进程占用CPU的百分比 id:空闲CP

qq_27924553的博客 647

【shell基础】01、常用的字符处理命令

目录wc,cut,sort,uniq,tr,paste,split1、文本统计:wcwc [OPTION]... [FILE]... 不指定选项默认:输出每个指定文件的行数、单词数和字节数,如果指定了多于一个文件,继续给出所有相关数据的总计。如果没有指定文件,或者文件为"-",则从标准输入读取数据。 -l, --lines 输出行数统计-w...

weixin_33726313的博客 515
上一篇: volatile
下一篇: 不用临时变量,交换两个变量的值
ecjtuync
博客等级 码龄20年 157粉丝 164原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值