【数据结构与算法】选择排序篇----详解直接插入排序和哈希排序【图文讲解】
欢迎来到CILMY23的博客
🏆本篇主题为:【数据结构与算法】选择排序篇----详解直接插入排序和哈希排序
🏆个人主页:CILMY23-CSDN博客
🏆系列专栏:Python | C++ | C语言 | 数据结构与算法 | 贪心算法 | Linux | 算法专题 | 代码训练营
🏆感谢观看,支持的可以给个一键三连,点赞关注+收藏。
前言
本期要讲解的是常见排序算法中的插入排序,插入排序又分两种,一种是直接插入排序,一种是希尔排序。

一、直接插入排序
1.1 插入排序的基本思想:
插入排序是一种简单的插入排序方法,其基本思想是:
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。
实际中我们玩扑克牌时,就用了插入排序的思想,我们从桌面抽一张牌,然后把牌按照我们所想的情况排序,插入到合适的位置,这就是插入排序的大致过程。

1.2 直接插入排序操作:
当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与 array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移

1.3 直接插入排序的特性总结:
- 元素集合越接近有序,直接插入排序算法的时间效率越高
- 时间复杂度:O(N^2)(逆序),最好情况是O(N) (顺序有序)
- 空间复杂度:O(1),它是一种稳定的排序算法
- 稳定性:稳定
1.4 代码实现
第一部分:
先写单趟的排序,现在取 end 之前的位置都是有序的,要比对的数值是 end+1 的位置数,这里我们用一个变量 tmp 来存储。
我们想实现升序的tmp
如果 tmp 比 end 位置的值小,那么就要把 end 位置的数值往后移动,end 往前移动,直到我们找到 tmp 比 end 位置的数值小,我们就可以直接插入。

特殊情况:
当 end+1 处的位置为最小值时,此时 end 为 -1 ,tmp 也就是 end+1 的位置处于 0 。

代码:
首先先不管end 是多少,我们知道[0,end]是有序,那end + 1 位置就是我们要比较的数,假设这个数比end位置小,那前面的位置就往后移动,直到数组尽头,或者找到比 end位置要大的数,在这个数的后面进行插入。
int end;
int tmp = a[end+1];
while(tmp < a[end])
{a[end+1] = a[end];end--;
}
a[end+1] = tmp
为什么最后是end+1?
取第二种极端情况,也就是插入排序的end走到尽头了,此时end 为 -1 这时候我们要在数组下标0的位置插入,所以要+1。
第二部分
确认多趟的情况 ,首先得保证前 end 都是有序的,想要确认end前有序,我们就再套一层循环,从0开始,让 end 从 0 的位置开始,遍历每个数值过去,这样整个数组都可以实现排序了。
void Insert_Sort(int* a, int n)
{for (int i = 0; i < n - 1; i++){int end = i;int tmp = a[end + 1];while (end >= 0){if (tmp < a[end]){a[end + 1] = a[end];end--;}else{break;}}a[end + 1] = tmp;}
}
1.5 动图理解

二、希尔排序(缩小增量排序)
2.1 基本思想
希尔排序法又称缩小增量法。
希尔排序法的基本思想是:
先选定一个整数,把待排序文件中所有记录分成按距离的个组,所有距离为gap的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达gap=1时,所有记录在统一组内排好序。
例如下图:
第一趟排序,gap = 5,从第一个数开始,每隔五个数取一组,9和4为一组;1和8为一组;2和6为一组;5和3为一组,7和5为一组,这样整个数组都分好了,然后在每个小组里面进行排序,9和4排序,因为9比4大,所以9在后面,4在前面,以此类推……
第二趟排序,gap = 3,从第一个数开始,每隔三个数取一组,4,2,5,8,5为一组;1,3,9,6,7为一组;这样整个数组就又分好了,然后在每个小组里面进行排序,4,2,5,8,5排序,排好后,就是4,2,5,8,5.同样以此类推排第二个小组。
在这样的排序下就逐渐接近了有序的数组。我们把这样的操作叫做预排序。
最后第三趟排序,当gap == 1时,你会发现,这个跟直接插入排序没有区别,开始取第一个数,保证第一个数有序,然后开始走直接插入的思想。

通过这样的过程我们就可以发现,直接插入排序也是希尔排序中的一步骤。
2.2 希尔排序的特性总结:
1. 希尔排序是对直接插入排序的优化。
2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样排序起来就会很快。对整体而言,可以达到优化的效果。
3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定,但也有大致算出来的。估计结果为O(n^1.3)
4. 稳定性:不稳定
2.3 希尔排序代码
void Shell_Sort(int *a,int n)
{int gap = n;while (gap > 1){gap = gap / 2;for (int i = 0; i < n - gap; i++){int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{tmp;}}a[end] = tmp;}}
}
2.4 希尔排序操作详解
希尔排序分两步走,一步是预排序,它的目的是让整个数组接近有序,第二步是直接插入排序。
第一种预排序(一组一组排序):
预排序的思路如下:
- 先把数组分成以gap为距离的各个小组
- 把分好的各单位小组进行插入排序
- 对每个小组进行插入排序
第一步:
假设我们现在有这样的三个小组,分别用红,橙,绿三种颜色进行标记。

把红色的第一个小组单独拿出来

我们标上下标,我们发现对这一个小组进行插入排序,原先的end+1就变成了end+gap。
现在是交换红色的部分,橙色和绿色我们并不在乎。,因为tmp < nums[end],所以只需要比较end处和end+gap处的值,然后继续直接插入排序的操作即可。

我们可以仿照直接插入排序写出如下的红色单区排序。
int gap = 3;
int end = 0;
int tmp = a[end + gap];
while (end >= 0)
{if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{tmp;}
}
a[end] = tmp;
第二步:
然后控制多个红色小组

我们套一层for循环,注意,j不能超过n-gap,防止end+gap越界。
最大的地方是:end+gap = n - 1
所以 j == end <= n-gap-1 == j < n - gap。
int gap = 3;
for (int j = 0; j < n - gap; j += gap)
{int end = 0;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{tmp;}}a[end] = tmp;
}
第三步:
控制多个组进行插入排序
int gap = 3;
for (int i = 0; i < gap; i++)
{for (int j = 0; j < n - gap; j += gap){int end = 0;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{tmp;}}a[end] = tmp;}
}
第二种预排序(多组并排):
其实这里的多组并排原理很简单,就是让end按照顺序走下去:

也就是将第二步和第三步合并了,这就很接近我们刚开始的步骤。

所以预排序:
gap越大,大的值更快调整到后面,小的值更快调用到前面, 越不接近有序
gap越小, 跳的越慢 越接近有序,如果gap==1,那就是插入排序。
代码:
end每次只走一步,这样一组组的跳,就是多组并排了。
for (int i = 0; i < n - gap; i++)
{int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{tmp;}}a[end] = tmp;
}
第二步 直接插入排序
要想最后接近有序,每次gap就要变化,最后一次gap==1,所以gap要跟着n进行变化
所以在外围添加一个循环,当gap > 1的时候是预排序,当gap == 1的时候是直接插入排序。
int gap = n;
while (gap > 1)
{gap = gap / 2;//觉得一次2太小//gap = gap / 3 + 1//...
}
2.5 希尔排序动图

🛎️感谢各位同伴的支持,本期数据结构与算法---选择排序篇就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞,关注+收藏,若有不足,欢迎各位在评论区讨论。
相关文章:
【数据结构与算法】选择排序篇----详解直接插入排序和哈希排序【图文讲解】
欢迎来到CILMY23的博客 🏆本篇主题为:【数据结构与算法】选择排序篇----详解直接插入排序和哈希排序 🏆个人主页:CILMY23-CSDN博客 🏆系列专栏:Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux…...
SpringBoot实战:多表联查
1. 保存和更新公寓信息 请求数据的结构 Schema(description "公寓信息") Data public class ApartmentSubmitVo extends ApartmentInfo {Schema(description"公寓配套id")private List<Long> facilityInfoIds;Schema(description"公寓标签i…...
解决mysql,Navicat for MySQL,IntelliJ IDEA之间中文乱码
使用软件版本 jdk-8u171-windows-x64 ideaIU-2021.1.3 mysql-essential-5.0.87-win32 navicat8_mysql_cs 这个问题我调试了好久,网上的方法基本上都试过了,终于是解决了。 三个地方结果都不一样。 方法一 首先大家可以尝试下面这种方法:…...
虚拟环境操作
1、对虚拟环境的操作 查看虚拟环境列表 conda env list 创建虚拟环境 conda create -n 虚拟环境名称 python3.x 激活虚拟环境 conda activate 虚拟环境名称 退出虚拟环境 conda deactivate 删除虚拟环境 conda remove -n 虚拟环境名称 all 2、对虚拟环境下的包的操作…...
企业网三层架构
企业网三层架构:是一种层次化模型设计,旨在将复杂的网络设计分成三个层次,每个层次都着重于某些特定的功能,以提高效率和稳定性。 企业网三层架构层次: 接入层:使终端设备接入到网络中来,提供…...
node.js的安装及学习(node/nvm/npm的区别)
一、什么是node、nvm和npm 1.Node.js node.js 一种Javascript编程语言的运行环境,能够使得javascript能够脱离浏览器运行。以前js只能在浏览器(也就是客户端)上运行,node.js将浏览器中的javascript运行环境进行封装的,…...
性能优化篇:用WebSocket替代传统的http轮循
当我还是初级菜鸟时,我只会写定时器定时调用接口,发起http请求,定时轮训请求接口,返回最新数据,定时器开启的多了还会引起页面卡顿的性能问题,虽然及时销了但还是会影响流畅问题。然后技术leader一声令下说改成websoket的请求方式,为什么这么做呢?下面来谈谈WebSocket相…...
virtualbox的ubuntu默认ipv4地址为10.0.2.15的修改以及xshell和xftp的连接
virtualbox安装Ubuntu后,默认的地址为10.0.2.15 我们查看virtualbox的设置发现是NAT 学过计算机网络的应该了解NAT技术,为了安全以及缓解ip使用,我们留了部分私有ip地址。 私有IP地址网段如下: A类:1个A类网段&…...
Codeforces Round 957 (Div. 3)(A~D题)
A. Only Pluses 思路: 优先增加最小的数,它们的乘积会是最优,假如只有两个数a和b,b>a,那么a 1,就增加一份b。如果b 1,只能增加1份a。因为 b > a,所以增加小的数是最优的。 代码: #include<bi…...
fedora 40 安装拼音输入法
仅做参考,一般主流linux版本在安装完成后,都会自带中文输入法。而需要配置中文输入法的小众发行版往往软件仓库自带的依赖不全。 1,sudo dnf install ibus 2,sudo dnf install im-chooser 3,sudo dnf install ibus-libpinyin 4,在终端输入im-choose…...
Chromium CI/CD 之Jenkins实用指南2024-如何创建新节点(三)
1. 前言 在前一篇《Jenkins实用指南2024-系统基本配置(二)》中,我们详细介绍了如何对Jenkins进行基本配置,包括系统设置、安全配置、插件管理以及创建第一个Job。通过这些配置,您的Jenkins环境已经具备了基本的功能和…...
Git代码管理工具 — 3 Git基本操作指令详解
目录 1 获取本地仓库 2 基础操作指令 2.1 基础操作指令框架 2.2 git status查看修改的状态 2.3 git add添加工作区到暂存区 2.4 提交暂存区到本地仓库 2.5 git log查看提交日志 2.6 git reflog查看已经删除的记录 2.7 git reset版本回退 2.8 添加文件至忽略列表 1 获…...
Linux——多线程(五)
1.线程池 1.1初期框架 thread.hpp #include<iostream> #include <string> #include <unistd.h> #include <functional> #include <pthread.h>namespace ThreadModule {using func_t std::function<void()>;class Thread{public:void E…...
张量分解(4)——SVD奇异值分解
🍅 写在前面 👨🎓 博主介绍:大家好,这里是hyk写算法了吗,一枚致力于学习算法和人工智能领域的小菜鸟。 🔎个人主页:主页链接(欢迎各位大佬光临指导) ⭐️近…...
第三方配件也能适配苹果了,iOS 18与iPadOS 18将支持快速配对
苹果公司以其对用户体验的不懈追求和对创新技术的不断探索而闻名。随着iOS 18和iPadOS 18的发布,苹果再次证明了其在移动操作系统领域的领先地位。 最新系统版本中的一项引人注目的功能,便是对蓝牙和Wi-Fi配件的配对方式进行了重大改进,不仅…...
Docker 部署 Nginx 并在容器内配置申请免费 SSL 证书
文章目录 dockerdocker-compose.yml申请免费 SSL 证书请求头参数带下划线 docker https://hub.docker.com/_/nginx docker pull nginx:1.27注: 国内网络原因无法下载镜像,nginx 镜像文件下载链接 https://pan.baidu.com/s/1O35cPbx6AHWUJL1v5-REzA?pw…...
模型评估与选择
2.1 经验误差与过拟合 错误率(error rate): 分类错误的样本数占样本总数的比例 精度(accuracy):1- 错误率 训练误差 / 经验误差:在训练集上的误差 泛化误差:在新样本上的误差 过…...
有必要把共享服务器升级到VPS吗?
根据自己的需求来选择是否升级,虚拟专用服务器 (VPS) 是一种托管解决方案,它以低得多的成本提供专用服务器的大部分功能。使用 VPS,您的虚拟服务器将与在其上运行的其他虚拟服务器共享硬件服务器的资源。但是,与传统的共享托管&am…...
LLM代理应用实战:构建Plotly数据可视化代理
如果你尝试过像ChatGPT这样的LLM,就会知道它们几乎可以为任何语言或包生成代码。但是仅仅依靠LLM是有局限的。对于数据可视化的问题我们需要提供一下的内容 描述数据:模型本身并不知道数据集的细节,比如列名和行细节。手动提供这些信息可能很麻烦&#…...
大模型系列3--pytorch dataloader的原理
pytorch dataloader运行原理 1. 背景2. 环境搭建2.1. 安装WSL & vscode2.2. 安装conda & pytorch_gpu环境 & pytorch 2.112.3 命令行验证python环境2.4. vscode启用pytorch_cpu虚拟环境 3. 调试工具3.1. vscode 断点调试3.2. py-spy代码栈探测3.3. gdb attach3.4. …...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
