希尔排序

2023-10-26

希尔排序又称为缩小增量排序,是直接插入排序算法的一种更高效的改进版本。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

  • 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
  • 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。

一、原理

既然希尔排序是插入排序的改进版本,那么它们之间必定有相似之处。那么得先回忆下什么是插入排序?插入排序就是将一个数组分为两个区间:已排序区间和未排序区间。然后在未排序区间中取一个数,将其按照顺序插入到已排序区间,重复操作,保证已排序区间一直有序。

希尔排序是将整个有序序列分割成若干小的子序列分别进行插入排序,使数组中任意间隔为n的元素都是有序的,这个间隔n称为增量

整个过程如下,首先设置一个增量大小,将原始序列中间隔为n的元素进行递增排序,使得这两个元素有序,接着对整个数组中所有元素都这样排序,当间隔为n的元素都有序之后,缩小增量,继续重复以上操作。

希尔排序用语言表述比较不直观,那就来看一张图,以数组{8,9,1,7,2,3,5,4,6,0}为例。

在增量=5时,首先进行排序的是(8,3)这一组数据,8>3,当(8,3)交换后,得到的序列为{3,9,1,7,2,8,5,4,6,0}。然后看看(8,3)这一组前面是否还有数据,发现没有了,于是进行下一组的排序。

下一组是(9,5),因为9>5,所以9和5进行交换,交换后的序列为{3,5,1,7,2,8,9,4,6,0},然后看看(9,5)这一组前面是否还有数据,发现还有一组我们上面排序后的(3,8),它们的顺序是对的,因此继续下一组的排序。

下一组是(1,4),因为1<4,所以1和4位置不变。然后看看(1,4)这一组前面是否还有数据,发现还有一组我们上面排序后的(3,8)和(5,9),它们的顺序是对的,因此继续下一组的排序。

重复以上操作,完成增量为5的排序后,将增量减少,继续下一次的排序,直到整个数组有序为止。

在这里插入图片描述

那么增量应该改什么值合适?一般来说,每次增量都除以2

二、示例代码

package Sort;
import java.util.Arrays;

public class ShellSort {
    public static void main(String[] args) {
        int[] arr = {8,9,1,7,2,3,5,4,6,0};
        shellSort(arr);
        System.out.println("arr = " + Arrays.toString(arr) );
    }

    public static void shellSort(int[] arr) {
        // 增量初始化为数组长度的一半,每次都/2
        for (int gap = arr.length / 2; gap > 0; gap /= 2) {
            //从增量位置那一组开始进行插入排序,直至完毕
            for (int i = gap; i < arr.length; i++) {
                int j = i;                 // 从i这个位置开始从后往前排序
                int temp = arr[j];         // 先保存i位置的元素值,用于交换
                // j - gap 就是代表与它同组的左边的元素
                // j - gap >= 0:不越界
                while (j - gap >= 0 && arr[j - gap] > temp) {
                    arr[j] = arr[j - gap];
                    j = j - gap;           // 这一组比较过了继续往前比较,确定前面也有序
                }
                arr[j] = temp;
            }
        }
    }

三、算法分析

平均时间复杂度 最好时间复杂度 最坏时间复杂度 空间复杂度 排序方式 稳定性
O(nlogn) O(nlog2n) O(n2 ) O(1) In-place 不稳定

希尔排序的性能无法准确量化,跟输入的数据有很大关系,其时间复杂度介于O(nlogn)O(n^2) 之间。对于大规模的序列(n>=1000),希尔排序都具有很高的效率。

希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小, 插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比O(n2)好一些。

由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

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

希尔排序 的相关文章

随机推荐

  • PHP取整,四舍五入取整、向上取整、向下取整、小数截取。

    PHP取整数函数常用的四种方法 1 直接取整 舍弃小数 保留整数 intval 2 四舍五入取整 round 3 向上取整 有小数就加1 ceil 4 向下取整 floor 一 intval 对变数转成整数型态 intval如果是字符型的会
  • 迭代器iterator

    能进行算术运算的迭代器只有随即访问迭代器 要求容器元素存储在连续内存空间里 vector string deque的迭代器是有加减法的 但是map set multimap multiset的迭代器是没有加减法的 list也不可以
  • minio老版本集成到k8s的yaml

    apiVersion apps v1 kind StatefulSet metadata name minio spec replicas 1 serviceName minio selector matchLabels name mini
  • Android WebView使用详解及注意事项

    未经本人授权 不得转载 否则必将维权到底 目前很多公司的 App 就只使用一个 WebView 作为整体框架 App 中的所有内容全部使用 HTML5 进行展示 这样只需要写一次 HTML5 代码 就可以在 Android 和 iOS 平台
  • Android textAppearance的属性设置及TextView属性详解

    http blog csdn net jaycee110905 article details 8762238 textAppearance的属性设置 android textAppearance android attr textAppe
  • html实现蜂窝菜单

    效果图 CSS样式 keyframes fade in mkmxd 1 0 filter blur 20px opacity 0 to filter none opacity 1 keyframes drop in mkmxd 1 0 tr
  • 【图片+代码】:GCC 链接过程中的【重定位】过程分析

    目录 示例代码 sub o 文件内容分析 段信息 符号表信息 main o 文件分析 段信息 符号表信息 绝对寻址 相对寻址 重定位表信息 可执行程序 main 段信息 符号表信息 绝对地址重定位 相对地址重定位 总结 别人的经验 我们的阶
  • 看京东架构师如何解决,数据库读写分离与事务纠缠的坑

    本篇文章讨论在数据库读写分离时使用事务的那些坑 1 在读写分离时会不会造成事务主从切换错误 一个线程在Serivcie时Select时选择的是从库 DynamicDataSourceHolder中ThreadLocal对应线程存储的是sla
  • SD卡学习笔记

    每个sector为512B 与IDE磁盘一样 通过读写命令读取一个多个sector 主控程序不需要关注SD具体是怎么实现读写与擦写的 每个sector可以耐受100 000次写操作 无限次读操作 每当sector被用命令erase命令擦除了
  • 三星被曝因ChatGPT泄露芯片机密!韩媒惊呼数据「原封不动」直传美国,软银已禁止员工使用...

    点击上方 AI遇见机器学习 选择 星标 公众号 第一时间获取价值内容 明敏 萧箫 发自 凹非寺 量子位 公众号 QbitAI 三星引入ChatGPT不到20天 就发生3起数据外泄事件 其中2次和半导体设备有关 1次和内部会议有关 消息一经释
  • Java 单测—static方法

    单测 static方法 静态方法的单测 静态方法的单测 方法上加注解 PrepareForTest 静态方法所在的类 class 调用测试方法前先要mock出类 Before public void setUp throws Excepti
  • 爱可生MySQL开源数据传输中间件DTLE首次技术分享

    10月27日 上海爱可生信息技术股份有限公司赞助的 3306 技术 Meetup 武汉站成功举办 爱可生技术服务总监洪斌分享了 MySQL 开源数据传输中间件架构设计实践 的主题演讲 并对爱可生10月24日最新开源项目 DTLE 相关技术细
  • Java岗面试:美国java程序员要求

    正文 在写这个文章之前 我花了点时间 自己臆想了一个电商系统 基本上算是麻雀虽小五脏俱全 我今天就用它开刀 一步步剖析 我会讲一下我们可能会接触的技术栈可能不全 但是够用 最后给个学习路线 Tip 请多欣赏一会 每个点看一下 看看什么地方是
  • cpu的架构

    明天继续搞一下cache 还有后面的 下面是cpu框架图 开始解释cpu 1 控制器 控制器又称为控制单元 Control Unit 简称CU 下面是控制器的组成 1 指令寄存器IR 是用来存放当前正在执行的的一条指令 当一条指令需要被执行
  • 单线程 JavaScript 的异步机制与经典 for 循环面试题

    从一个经典的 for 循环问题开始 for var i 1 i lt 5 i setTimeout function timer console log i i 1000 输出是 每隔1秒 输出一个6 共5次 原理 这样的输出 是由 Jav
  • 逆矩阵的性质

    矩阵的逆矩阵具有许多有用的性质 1 如果MM 1 I 则M 1M I 2 M1M2 1 M2 1M1 1 3 M 1 1 M 4 M 1 1 M 1 0 说明 M 1 表示矩阵M的逆 摘自 lt lt 计算机图形学几何工具算法详解 gt g
  • 测试工作内容(一)---需求分析

    当我们要做一个项目时 不管项目是一个大的软件 还是一个小的功能模块 我们在执行之前都要搞清楚 这个项目是做什么的 将会实现哪些功能需求 在时间点范围内需要我们做什么 做哪些工作 所追溯的就是需求 需求分析都需要做哪些事情 怎样做 包括以下四
  • JAVA注释

    单行注释 单行注释 多行注释 多行注释 文档注释 文档注释 放在类定义 方法 field 内部类之前才有效 此行前面这个星号只是为了好看 只有第一行和最后一行的 和 才有效 文档注释可以被javadoc命令抽取出api文档格式 javado
  • 木马编程-手把手带你进入木马的世界之木马编程

    一 基础知识 1 1 木马病毒 木马 Trojan 这个名字来源于古希腊传说 荷马史诗中木马计的故事 Trojan一词的本意是特洛伊的 即代指特洛伊木马 也就是木马计的故事 木马会想尽一切办法隐藏自己 主要途径有 在任务栏中隐藏自己 这是最
  • 希尔排序

    目录 一 原理 二 示例代码 三 算法分析 希尔排序又称为缩小增量排序 是直接插入排序算法的一种更高效的改进版本 希尔排序是基于插入排序的以下两点性质而提出改进方法的 插入排序在对几乎已经排好序的数据操作时 效率高 即可以达到线性排序的效率