“希尔排序:打破时间瓶颈的排序算法 “

news2024/11/16 13:33:40

文章目录

  • 🔍什么是希尔排序
  • 🔑希尔排序分组思想
  • 📈希尔排序的优缺点
  • 👨‍💻希尔排序代码剖析

🔍什么是希尔排序

希尔排序(Shell Sort)是插入排序的一种高效率的改进版本,也称为缩小增量排序。它基于插入排序,但使用了不同的增量序列,通过将序列分成若干个子序列进行插入排序,逐步减小增量,最终完成排序。

希尔排序法的基本思想是:先选定一个整数,把待排序的数据所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。​ 每次排序让数组接近有序的过程叫做预排序,最后一次等于1时插入是直接插入排序。


🔑希尔排序分组思想

在这里插入图片描述

  1. 我们首先从间隔为5分组,间隔为gap分为一组,总计gap组,多组并排
    在这里插入图片描述

gap代表间隔,此时为我们已经分好组了

第一组: 9 4
第二组: 1 8
第三组: 2 6
第四组: 5 3
第五组: 7 5

我们对这几组分别进行排序分别得到:
在这里插入图片描述

  1. 我们缩小gap增量,使的变成2

在这里插入图片描述
此时为我们分组是

第一组: 4 2 5 8 5
第二组: 1 3 9 6 7

我们对这两组分别进行排序分别得到:
在这里插入图片描述

  1. 缩小gap增量,使的变成1,变成1就是已经变成插入排序了。到这里已经是最后一步了。
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/58c71fb2a4c9479fa93bc927f6e7eb72.png

gap >1 就是预排序
gap越大,大的数可以更快的到后面,小的数可以更快的到前 越不接近有序
gap越小,大的小的挪动越慢,但是他越接近有序
gap会逐渐缩小,间隔也会逐渐缩小。
整体的数据会更加趋于有序,这个时候使用直接插入排序效率会更高。
gap == 1,就是直接插入排序


📈希尔排序的优缺点

希尔排序是基于插入排序的一种排序算法,它通过将一串待排序的数据分成多个子序列来实现排序,最终将这些子序列合并成一个有序序列。相比插入排序,希尔排序的优缺点如下:

  • 优点
  1. 相对于其他简单的排序算法(如冒泡排序、选择排序等),希尔排序的时间复杂度较低,尤其是对于大规模数据的排序。

  2. 希尔排序是一种原地排序算法,不需要额外的存储空间。

  3. 由于希尔排序改变了插入排序中元素的位置,从而减少了元素之间的比较和交换次数,因此希尔排序在实际应用中展现出了较高的排序效率。

  • 缺点
  1. 希尔排序的时间复杂度与增量(gap)序列有关,不同的增量(gap)序列会影响排序的效率。
  2. 希尔排序是一种不稳定的排序算法,相同的元素在排序后可能会改变相对位置。

👨‍💻希尔排序代码剖析

  • 确定增量序列gap

    1. 先把gap给成数组的长度
      int gap = n
    2. 确定 增量序列gap
      gap=gap/3+1 +1可以保证最后一次一定是1 即最后一次是直接插入排序
  • 确定循环条件外层循环条件
    while (gap > 1)该while循环的作用是随着跨度gap的不断减小,进行希尔排序的每一轮迭代,直到跨度为1时结束循环,完成希尔排序。

  • 确定循环控制每组数据进行插入排序的过程

    for (int i = 0; i < n - gap; ++i) n - gap表示数组a中第一组数据的最后一个元素下标。在希尔排序中,我们将数组n个元素分成若干组(组与组之间的元素下标相差gap),每组中的元素个数通常为gap。因此,在对每组数据进行插入排序时,需要在第一组数据中从第一个元素开始进行比较,直到最后一个元素。由于每组数据中的元素下标相差gap,所以第一组数据的最后一个元素下标为n-gap。因此,for循环的条件判断语句可以写为 i < n - gap。

  • 使用两个变量确定当前组需要排序的范围和下一个待插入的元素。
    int end = i
    int tmp = a[end + gap]

  • 里层循环不断向后更新位置
    (end >= 0)不断查找当前元素 a[end] 在以 end-gap 为结尾的子序列中的正确位置,并将其插入到正确的位置中,直到 end 的值小于 0 为止

  • 判断 元素是否比待插入元素 tmp 大
    if (a[end] > tmp)
    {
    a[end + gap] = a[end]
    end-=gap 需要往后移动一个 gap 的位置,以便为下一个待插入元素腾出位置
    }

  • 实现待插入操作
    a[end + gap] = tmp 在这之前,我们通过 a[end + gap] = a[end]; 操作,已经将子序列中所有大于待插入元素的元素往后移动了一个 gap 的位置,以腾出正确的插入位置。现在,我们已经找到了待插入元素的正确位置,也就是以 end-gap 为结尾的子序列中的某个位置。因此,直接将待插入元素(tmp)赋值给 a[end+gap],实现了在子序列中插入待插入元素的目的。

void ShellSort(int* a, int n)
{
    int gap = n;
    while (gap > 1)  // 当跨度为1时,就是普通的插入排序,不需要再进行希尔排序了
    {
    // 通过除以3再加1的方式来缩小跨度 +1可以保证最后一次一定是1,
    //这是希尔排序中常用的增量序列
        gap = gap / 3 + 1;  
        for (int i = 0; i < n - gap; ++i)  // 对每组数据进行插入排序
        {
            int end = i;  // end表示每组数据的最后一个元素的下标
            int tmp = a[end + gap];  // tmp表示当前组中下一个待插入的元素
            while (end >= 0)  // 在当前组中,从后往前找到tmp应该插入的位置
            {
                if (a[end] > tmp)  // 如果当前位置的元素比tmp大,就将该元素后移gap个位置,为tmp腾出位置
                {
                    a[end + gap] = a[end];
                    end -= gap;  // 继续向前查找
                }
                else  // 如果当前位置的元素比tmp小,就找到了tmp应该插入的位置
                {
                    break;
                }
            }
            a[end + gap] = tmp;  // 将tmp插入到当前组的合适位置
        }
    }
}

在上面的代码中,我们可以看到,希尔排序主要包含两个阶段:预排序阶段和插入排序阶段。其中,预排序阶段是通过不断缩小跨度来实现的,而插入排序阶段则是对每组数据进行插入排序。在预排序阶段中,我们使用了一个常用的增量序列: gap=gap/3+1,这个增量序列可以保证最后一次的跨度一定是1,从而保证了最后一次排序是普通的插入排序。

在插入排序阶段中,我们首先定义了一个变量end,表示每组数据的最后一个元素的下标。然后,我们将当前组中下一个待插入的元素存储在了tmp变量中。接着,我们从后往前遍历当前组中的元素,将比tmp大的元素后移gap个位置,为tmp腾出位置。最后,我们将tmp插入到当前组的合适位置。

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

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

相关文章

浏览器缓存方式有哪些(cookie、localstorage、sessionstorage)

浏览器缓存方式 概要 http缓存 基于HTTP协议的浏览器文件级缓存机制 websql 只有较新的chrome浏览器支持&#xff0c;并以一个独立规范形式出现 indexDB 一个为了能够在客户端存储可观数量的结构化数据&#xff0c;并且在这些数据上使用索引进行高性能检索的 API Cooki…

v-model双向绑定指令

文章目录 前言v-model.lazy 延迟同步v-model.trim 去掉空格 前言 v-model指令是Vue.js中实现双向数据绑定的一种重要机制。它可以将表单控件的值与Vue.js实例中的数据进行双向绑定&#xff0c;即当表单控件的值发生变化时&#xff0c;Vue.js实例中的数据也会随之更新&#xff…

qt实现漂亮主页面

模仿自feiyangqingyun的博客_CSDN博客-Qt/C控件SDK使用示例,Qt/C音视频开发,Qt/C自定义控件领域博主 1.无边框窗口可移动 #ifndef MOVABLE_WIDGET_H #define MOVABLE_WIDGET_H#include <QWidget>class movable_widget:public QWidget { public:movable_widget(QWidget *…

华为荣耀6X(BLN-AL20)解锁全过程

这台旧手机一直闲置&#xff0c;想用它做测试机&#xff0c;所以必须先解锁。在此之前我已将手机改成了直供电&#xff0c;所以图片里没有电池&#xff0c;但是目前直供电方案并不完美&#xff0c;除了直供电线要插&#xff0c;尾插也要插上&#xff0c;淘宝卖家给出的理由是普…

部署 CNI网络组件

部署 flannel K8S 中 Pod 网络通信&#xff1a; ●Pod 内容器与容器之间的通信 在同一个 Pod 内的容器&#xff08;Pod 内的容器是不会跨宿主机的&#xff09;共享同一个网络命令空间&#xff0c; 相当于它们在同一台机器上一样&#xff0c;可以用 localhost 地址访问彼此的端…

如何看待程序员的高薪现象?

点击上方关注 “终端研发部” 设为“星标”&#xff0c;和你一起掌握更多数据库知识 最近在知乎上看到这样个话题&#xff1a; 难道不应该吗&#xff1f; 本人月薪八千&#xff0c;在北京一线&#xff0c;拿着最基础的工资&#xff0c;上的加班最频繁的班&#xff0c;干最累的活…

STM32模拟SPI协议控制数字电位器MCP41010电阻值

STM32模拟SPI协议控制数字电位器MCP41010电阻值 MCP41010是单路8位分辨率数字电位器&#xff0c;通过SPI接口可控制电位器阻值分配&#xff0c;相当于PW0端在PA0和PB0之间滑动。如下图所示&#xff1a; MCP41010是10K欧姆规格的数字电位器&#xff0c;即PA0和PB0之间的阻值恒…

Spring Boot 中的 @HystrixCommand 注解

Spring Boot 中的 HystrixCommand 注解 简介 在分布式系统中&#xff0c;服务之间的调用是不可避免的。但随着服务数量的增加&#xff0c;服务之间的依赖关系也会变得越来越复杂&#xff0c;服务的故障也会变得越来越常见。一旦某个服务出现故障&#xff0c;它所依赖的服务也…

Helm之深入浅出Kubernetes包管理工具基础

Helm 基础 作者&#xff1a;行癫&#xff08;盗版必究&#xff09; 一&#xff1a;Helm 简介 1.简介 ​ Helm 是 Kubernetes 的包管理器&#xff1b;它提供了提供、共享和使用为 Kubernetes 构建的软件的能力&#xff1b;是CNCF的毕业项目&#xff0c;自 Helm 加入 CNCF 以来…

【Canal】从原理、配置出发,从0到1完成Canal搭建

文章目录 简介工作原理MySQL主备复制原理canal 工作原理 Canal架构Canal-HA机制应用场景同步缓存 Redis /全文搜索 ES下发任务数据异构 MySQL 配置开启 binlog扩展statementrowmixed 配置权限 Canal 配置配置启动报错解决 实战引入依赖代码样例测试 前几天在网上冲浪的时候发现…

MYSQL03高级_新增用户、授予权限、授权底层表结构、角色理解

文章目录 ①. 登录服务器操作②. 用户的增删改③. 修改用户密码④. MySQL8密码管理⑤. 权限列表及原则⑥. 授予查看回收权限⑦. 底层权限表操作⑧. 角色的理解 ①. 登录服务器操作 ①. 启动MySQL服务后,可以通过mysql命令来登录MySQL服务器,命令如下: mysql –h hostname|hos…

chatgpt赋能python:搜索Python答案的软件

搜索Python答案的软件 介绍&#xff1a;什么是搜索Python答案的软件&#xff1f; 搜索Python答案的软件是一种工具&#xff0c;可以帮助编程人员快速地找到他们在编写Python代码时遇到的问题的答案。这种软件可以搜索各种不同的网站&#xff0c;以帮助用户找到最适合他们问题…

实例006 菜级联菜单

实例说明 如果管理程序功能菜单非常多&#xff0c;一些功能中又包括许多子功能&#xff0c;这时可以使用级联菜单来组织系统的各个功能。实例运行结果如图1.6所示。 图1.6 级联菜单 技术要点 制作级联菜单需要使用MenuStrip控件。 注意&#xff1a;在使用级联菜单时最好不要…

Redis三种模式——主从复制、哨兵、集群

目录 一、概述 二、 Redis 主从复制 1.主从复制的作用 2. 主从复制流程 3. 搭建Redis 主从复制 3.1准备环境 3.2安装redis 3.3创建redis工作目录 3.4环境变量 3.5定义systemd服务管理脚本 3.6修改 Redis 配置文件&#xff08;Master节点操作&#xff09; 3.7修改 …

我在「亚马逊云科技中国峰会」做讲师 - 「程序员的社区成长史」

文章目录 ⭐️ Part - 〇&#xff1a;开场的自我介绍⭐️ Part - ①&#xff1a;程序员的学习从技术社区开始&#x1f31f; 编程初学者共同面对的迷茫&#x1f31f; 加入一个适合自己的技术社区&#x1f31f; 反哺社区做有价值的贡献者 ⭐️ Part - ②&#xff1a;与技术社区的…

STM32F4 WiFi上传温度【ds18b20传感器、网络通信】

通过WIFI或GPRS上传温度到云端 本篇博客将介绍如何使用WIFI或GPRS模块将温度数据上传到云端。我们将涵盖连接网络的过程、上传数据的过程以及相关代码。 准备工作 在开始之前&#xff0c;我们需要准备以下材料&#xff1a; STM32F4开发板温度传感器&#xff08;例如18B20&a…

ch0_汇编介绍

1. 汇编作用 1.1 1.2 1.3 2.  机器语言到汇编语言 2.1 2.2 2.3 3.  计算机的组成 3.1 指令和数据是存放在存储器中的&#xff0c; 而计算机包含多种存储器&#xff1b; 但是&#xff0c;在计算机工作的过程中&#xff0c; 指令和数据则必须存放到内存中。 而对于…

代码随想录二刷day41 | 动态规划之 343. 整数拆分 96.不同的二叉搜索树

day41 343. 整数拆分确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp的初始化确定遍历顺序举例推导dp数组 96.不同的二叉搜索树确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 34…

【每日一题Day254】LC445两数相加Ⅱ | 链表反转 栈

两数相加Ⅱ【LC445】 给定两个 非空链表 l1和 l2 来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。 可以假设除了数字 0 之外&#xff0c;这两个数字都不会以零开头。 原来是专题模拟 反转链表 2022/11/4 思…