[数据结构] 基于插入的排序 插入排序希尔排序

标题:[数据结构] 排序#插入排序&希尔排序

@水墨不写bug



目录

(一)插入排序

实现思路:

插入排序实现: 

(二)希尔排序

希尔排序的基本思想: 

希尔排序的实现:


正文开始:

        排序是日常生活中常见的对数据的需求,排序有多重不同的方法,每一种方法都有各自的优缺点,本文来为你介绍两个思路类似的排序方法:插入排序和希尔排序。

(一)插入排序

       

        时间复杂度:O(N^2)

        空间复杂度:O(1)

        特点:元素越接近有序,插入排序的效率越高。

        稳定性:稳定

实现思路:

主要过程: 

        对于区间一个有序区间 [0,end] 将区间后的一个元素 nums[end+1] 插入到有序区间内。

由于nums[end+1]在移动元素时会被覆盖,需要一个临时变量tem暂时存储 nums[end+1],具体来说,将tem与nums[end]进行比较,如果

tem < nums[end]

则将end处的数据后移:

nums[end+1] = nums[end]

并将end--,继续比较。

如果

tem>=nums[end]

说明已经到达要插入的位置,直接break。

在出循环之后,将tem插入正确的位置即可:

nums[end+gap] = tem

整体实现注意事项:

        1.在实现过程中,可以先写内层循环,完成内层逻辑,再写外层循环。

        2.对于内层循环,进行循环的条件是 end>=0 ,由于外层循环end从0开始,如果内层进行循环的条件是end>0,那么如果end = 0,就无法进入循环。

        3.如何确定外层循环的区间?

        左区间从零开始;对于最大的区间,由于要将最后一个元素(size-1位置)插入到前面的区间 [0,size-2]内,所以end最大可取  size-2 。

        则区间为:

                [0,size-2](两闭区间)或者[0,size-1)(左闭右开区间)。

插入排序实现: 

#include<iostream>
#include<vector>
using namespace std;void InsertSort(vector<int>& nums)
{//外层循环,end从0开始遍历for (int i = 0; i < nums.size()-1; i++){//[0,end] end+1int end = i;int tem = nums[end + 1];//内层循环,end>=0时要进入循环while (end >= 0){if (nums[end] > tem){nums[end + 1] = nums[end];--end;}elsebreak;}nums[end + 1] = tem;}
}
void Print(vector<int> v)
{for (const auto& e : v)cout << e << " ";cout << endl;
}
int main()
{vector<int> nums = { 55,9,8,6,7,59,75,89,12,50 };Print(nums);InsertSort(nums);Print(nums);return 0;
}


(二)希尔排序

        希尔排序简单来说就是对插入排序的优化,它与插入排序的整体思路是一致的。想要写好希尔排序,就必须要讲究一个层次感,你需要明白希尔排序的几层循环到底是在干什么


希尔排序的基本思想: 

分组:

        将数组中间距为gap的数据分为一组,如图所示:(gap == 3)

可以将一组数据分为gap组:

        我们将每一组数据看做是一个小组(group),对于每一个小组,想要将他们排序,自然需要移动,由于小组内部数据相距gap,所以移动的步幅也是gap。

希尔第一层次:

        也就是插入排序内层循环的逻辑,唯一不同的是将步幅从1改为gap。

实现的操作:

        将一个数据 nums[end+gap] 插入到已经有序的区间 [0,end] 内部,并在插入后使整个区间保持有序。

        由于nums[end+gap]在移动元素时会被覆盖,需要一个临时变量tem暂时存储 nums[end+gap],具体来说,将tem与nums[end]进行比较,如果

tem < nums[end]

则将end处的数据后移:

nums[end+gap] = nums[end]

并将end-=gap,继续比较。

如果

tem>=nums[end]

说明已经到达要插入的位置,直接break。

在出循环之后,将tem插入正确的位置即可:

nums[end+gap] = tem

实现参考:

int end;
int tem = nums[end + gap];
while (end >= 0)
{if (tem < nums[end]){nums[end + gap] = nums[end];end -= gap;}elsebreak;
}
nums[end + gap] = tem;

 希尔第二层次:

        也就是插入排序外层循环的逻辑。

实现的操作:

        由于随着插入的进行,区间不断扩大,第二层次作用是不断改变区间的右端,和定位并保存需要插入的元素 nums[end+gap] 。

实现参考:

for (int i = 0; i < n - gap; i += gap)
{int end = i;int tem = nums[end + gap];while (end >= 0){if (tem < nums[end]){nums[end + gap] = nums[end];end -= gap;}elsebreak;}nums[end + gap] = tem;
}

希尔第三层次:

        前两层次实现了对一个group的排序,第三层就是要实现对所有group的排序。

实现的操作:

        外层创造循环变量j,对区间起点 i 制造偏移量:

for (int j = 0; j < gap; j++)
{for (int i = j; i < n - gap; i += gap){int end = i;int tem = nums[end + gap];while (end >= 0){if (tem < nums[end]){nums[end + gap] = nums[end];end -= gap;}elsebreak;}nums[end + gap] = tem;}
}

 希尔第四层次:

        前三层次完成了对某一特定gap下的预排序。第四层次就是要通过gap来逐渐让数组接近有序。

        gap的意义是让数据跳动的步幅增大,不同的大小的gap拥有不同的效果:

        如果gap较大,数据跳动的步幅更大,数据的移动更快,但是更不容易接近有序。

        对于较小的gap,数据步幅减小,数据移动的较慢,但是更容易接近有序;当gap取可取得的最小值1时,整个排序逻辑就会退化为插入排序。

实现的操作:

        通过特定的策略逐渐减小gap。

        经过研究,gap每次除三效果最好,但是为了避免gap小于1,于是在每次除三后再加上1,这样就是一种gap的取值策略。


void ShellSort(vector<int>& nums)
{int n = nums.size();int gap = n;while (gap > 1){gap = gap / 3 + 1;//....}
}

希尔排序的实现:


void ShellSort(vector<int>& nums)
{int n = nums.size();int gap = n;while (gap > 1){gap = gap / 3 + 1;for (int j = 0; j < gap; j++){for (int i = j; i < n - gap; i += gap){int end = i;int tem = nums[end + gap];while (end >= 0){if (tem < nums[end]){nums[end + gap] = nums[end];end -= gap;}elsebreak;}nums[end + gap] = tem;}}}
}

完~

未经作者同意禁止转载

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP同城多商户多行业系统小程序源码

同城新生态&#xff0c;解锁多商户多行业系统的无限魅力&#x1f306;&#x1f680; &#x1f308; 开篇&#xff1a;同城新纪元&#xff0c;多商户多行业系统引领潮流&#xff01; 想象一下&#xff0c;在同一个城市内&#xff0c;无论是美食探索、购物狂欢&#xff0c;还是…

Python在量化交易中的应用

量化交易近年来越来越受到投资者的青睐。Python因其简洁的语法和丰富的库&#xff0c;成为量化交易的首选编程语言。本文将从Python量化交易的基础知识、主要技术及其在实际交易中的应用三个方面进行介绍。 一、Python量化交易的基础知识 1. 量化交易的概念 量化交易是指利用…

东方通Tongweb发布vue前端

一、前端包中添加文件 1、解压vue打包文件 以dist.zip为例&#xff0c;解压之后得到dist文件夹&#xff0c;进入dist文件夹&#xff0c;新建WEB-INF文件夹&#xff0c;进入WEB-INF文件夹&#xff0c;新建web.xml文件&#xff0c; 打开web.xml文件&#xff0c;输入以下内容 …

sdwan是硬件还是网络协议?

SD-WAN&#xff08;Software-Defined Wide Area Network&#xff0c;软件定义广域网&#xff09;并不是一个硬件产品或单一的网络协议&#xff0c;而是结合了软件、硬件和网络技术的一种解决方案。SD-WAN的核心在于其软件定义的特性&#xff0c;它通过软件来控制和管理广域网的…

【BUG】RestTemplate发送Post请求后,响应中编码为gzip而导致的报错

BUG描述 20240613-09:59:59.062|INFO|null|810184|xxx|xxx||8|http-nio-xxx-exec-1|com.xxx.jim.xxx.XXXController.?.?|MSG接收到来自xxx的文件请求 headers:[host:"xxx", accept:"text/html,application/json,application/xhtmlxml,application/xml;q0.9,*…

Apache Seata分布式事务原理解析探秘

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 前言 fescar发布已有时日&#xff0c;分布式事务一直是业界备受关注的领域&#xff0c;fesca…

如何探索高效知识管理:FlowUs知识库体验很好

在当今信息爆炸的时代&#xff0c;有效的知识管理对于个人和团队的发展至关重要。FlowUs 知识库作为一款创新的知识管理工具&#xff0c;正逐渐成为众多用户的首选&#xff0c;为他们带来了高效、便捷和有条理的知识管理体验。 FlowUs 知识库的一大特色在于其简洁直观的界面设计…

雷池WAF动态防护功能初体验

一、 介绍 大名鼎鼎的雷池WAF最近新上了个名为 动态防护 的功能 所谓动态防护&#xff0c;是在用户浏览到的网页内容不变的情况下&#xff0c;将网页赋予动态特性&#xff0c;即使是静态页面&#xff0c;也会具有动态的随机性。 说白了就是给你网站的 html 和 js 代码加上加密…

前端与嵌入式开发通信之QWebChannel(Qt)

前端与嵌入式开发通信之QWebChannel 最近开发中需要用到和c开发的操作台进行通信的的需求&#xff0c;就找到了这个技术&#xff0c;记录一下 首先需要安装导入 qwebchannel npm i qwebchannel import { QWebChannel } from "qwebchannel"; 初始化qwebchannel并封…

哈喽GPT-4o,程序员如何通过GPT-4o提高办公效率

目录 一、编写工作汇报Prompt&#xff1a;我是一名Java开发工程师&#xff0c;请写一份工作总结&#xff0c;工作内容是一个SpringBootVue实现的图书管理系统&#xff0c;按下面的结构来撰写&#xff1a;1. 工作背景&#xff1b;2. 工作内容&#xff1b;3. 工作建议&#xff1b…

springboot中@bean注解的创建和使用

bean的创建顺序 在Spring Boot中&#xff0c;当一个配置类&#xff08;使用Configuration注解的类&#xff09;中定义了多个bean时&#xff0c;这些bean的创建顺序并不完全由它们在类中的声明顺序决定。Spring框架在创建和管理bean时&#xff0c;遵循了复杂的依赖注入和生命周…

简单仿写SpringIOC

gitee地址&#xff08;需要自取&#xff09;ioc_Imitation: 简单仿写IOC (gitee.com) 项目目录结构 Autowired Target(ElementType.FIELD) Retention(RetentionPolicy.RUNTIME) public interface Autowired { }Component Target(ElementType.TYPE) Retention(RetentionPoli…

文献笔记|综述|When Large Language Model Meets Optimization

When Large Language Model Meets Optimization 题目&#xff1a;当大型语言模型遇到优化时 作者&#xff1a;Sen Huang , Kaixiang Yang , Sheng Qi and Rui Wang 来源&#xff1a;arXiv 单位&#xff1a;华南理工大学 文章目录 When Large Language Model Meets Optimization…

Redis主从部署

文章目录 Redis主从部署1.下载安装Redis2.单点双副本主从配置1.修改配置信息2.修改配置文件redis.conf3.拷贝配置文件到每一个实例文件夹里4.修改每一个实例的端口和工作目录5.配置主从关系6.检查效果 3.哨兵模式监控主从1.创建实例目录2.复制配置文件并进行修改3.启动并测试 4…

Java增加线程后kafka仍然消费很慢

文章目录 一、问题分析二、控制kafka消费速度属性三、案例描述 一、问题分析 Java增加线程通常是为了提高程序的并发处理能力&#xff0c;但如果Kafka仍然消费很慢&#xff0c;可能的原因有&#xff1a; 网络延迟较大&#xff1a;如果网络延迟较大&#xff0c;即使开启了多线…

使用redis进行短信登录验证(验证码打印在控制台)

使用redis进行短信登录验证 一、流程1. 总体流程图2. 流程文字讲解&#xff1a;3.代码3.1 UserServiceImpl&#xff1a;&#xff08;难点&#xff09;3.2 拦截器LoginInterceptor&#xff1a;3.3 拦截器配置类&#xff1a; 4 功能实现&#xff0c;成功存入redis &#xff08;黑…

悠律凝声环Ringbuds Pro耳机:素皮纹理质感独一档,音质也拉满

悠律&#xff08;UMELODY&#xff09;推出的这款新品——凝声环开放式耳机&#xff0c;以其独特的设计风格和出色的音质表现赢得了众多消费者的喜爱。 在外观上&#xff0c;凝声环采用了时尚潮酷的设计理念&#xff0c;并且采用简约典雅素皮工艺&#xff0c;首次将“素皮”材料…

QT文件生成可执行的exe程序

将qt项目生成可执行的exe程序可按照以下步骤进行&#xff1a; 1、在qt中构建运行生成.exe文件&#xff1b; 2、从自定义的路径中取出exe文件放在一个单独的空文件夹中&#xff08;exe文件在该文件夹中的release文件夹中&#xff09;&#xff1b; 3、从开始程序中搜索qt&#xf…

提升Selenium在Chrome上的HTML5视频捕获效果的五个方法

在使用Selenium进行网页自动化测试时&#xff0c;捕获HTML5视频是一个常见的需求。然而&#xff0c;许多开发者发现&#xff0c;在使用Chrome浏览器时&#xff0c;视频捕获效果并不理想&#xff0c;经常出现视频背景为空白的问题。本文将概述五种方法&#xff0c;帮助提升Selen…

品牌渠道低价管控的思考与策略

消费者在购买产品时追求低价、货比三家&#xff0c;这无可非议。然而&#xff0c;产品低价就一定是好事吗&#xff1f;倘若品牌为了迎合消费者对低价的需求&#xff0c;一味追求低价引流&#xff0c;最终的结果只能是从源头压价&#xff0c;比如在原材料的选购、供应商的选择上…