数据结构 之 【排序】(直接插入排序、希尔排序)

目录

1.直接插入排序

1.1直接插入排序的思想

1.2直接插入排序的代码逻辑: 

1.3 直接插入排序图解 

1.4单趟排序代码(单个元素的排序逻辑)

1.5完整排序代码

1.6直接插入排序的时间复杂度与空间复杂度

1.7直接插入排序的优势 

2.希尔排序(缩小增量排序)

2.1希尔排序的思想

2.2希尔排序的代码逻辑

2.3希尔排序图解

2.4单单趟排序代码(对于特定的gap的一组元素的排序)

2.5单趟排序代码(对于特定的gap的分组排序)

2.5.1一组排好序再排另一组

2.5.2 根据元素的所在组进行直接插入排序

 2.6完整排序代码

2.6.1一组排好序再排另一组

 2.6.2 根据元素的所在组进行直接插入排序

2.7希尔排序的时间复杂度与空间复杂度


所有排序的实现皆以升序为例

1.直接插入排序

1.1直接插入排序的思想

直接插入排序的思想就是将待排序的数插入到一组有序的数中

就像打扑克牌摸牌阶段,我们一张一张摸牌并整理有序的过程就是直接插入排序的过程 

1.2直接插入排序的代码逻辑: 

创建 end 变量,初始化为有序数组中最后一个数的下标

创建 tmp变量,初始化为待排序的数值

然后将 tmp变量 与 end位置的数 从后向前 依次比较,按需要(升降序)挪动与存放数据

1.3 直接插入排序图解 

如果 tmp 比 end位置的数 大tmp 存放在 end + 1 位置 

如果 tmp 比 end位置的数 小先将end位置的数向后移动一位,再 --end

然后继续将 tmp 与 end位置的数 从后向前 依次比较

如果 tmp 比 end位置的数 大tmp 存放在 end + 1 位置 

(1) 依次比较,这显然是一个循环

(2) tmp可能比所有值都小,即 end 可能 小于0 (数组下标的角度),这可以作为循环结束条件

(3) 实现正确的情况下, tmp 永远存放在 end + 1 位置

1.4单趟排序代码(单个元素的排序逻辑)

int end;
int tmp;
while (end >= 0){if (tmp < a[end]){a[end + 1] = a[end];--end;}else break;
}
a[end + 1] = tmp;

tmp 比 end位置的数 小一直挪动数据并--end

tmp 比 end位置的数 大 就跳出循环

因为我们知道 (实现正确下) tmp 永远放在 end + 1 位置

选择在循环外面控制 tmp 存放的位置可以解决 end<0 与 end >= 0两种情况

end >= 0,即 tmp 不存放在数组中首元素的位置

end < 0,即 tmp 比 所有数组元素都要小,不断--end,直到循环结束,最终放在第一个位置

1.5完整排序代码

void InsertSort(int* a, int n){ for(int i = 0; i < n - 1; ++i){int end = i;int tmp = a[i + 1];while (end >= 0){if (tmp < a[end]){a[end + 1] = a[end];--end;}else break;}a[end + 1] = tmp;}
}

在单趟排序的基础上控制end与tmp即可完整代码

一个数我们可以看作是有序的,所以 end初始值应为0,tmp初始值为数组中的第二个数

一趟比较完毕,前两个数有序了,end位置往后挪,tmp被赋值为下一个数

这显然也是一个循环........

1.6直接插入排序的时间复杂度与空间复杂度

直接插入排序的最坏情况就是输入数组完全逆序

假设数组有N个元素,即

第1次插入操作(从第2个元素(索引1)开始插入):前1个已排序元素一共后移1次

第2次插入操作:前2个已排序元素一共后移2次

第3次插入操作:前3个已排序元素一共后移3次

.........

第 N - 1 次插入操作:前N - 1 个已排序元素一共后移N - 1 次

那么移动总次数就是 ((N - 1)* N)/ 2 

所以时间复杂度就是 O(N^2)

 直接插入排序创建的变量只有i、end、tmp,变量的数量固定,所有操作均在原数组上完成

所以空间复杂度为O(1)

1.7直接插入排序的优势 

元素集合越接近有序,直接插入排序算法的时间效率越高

2.希尔排序(缩小增量排序)

2.1希尔排序的思想

希尔排序的思想就是通过分组直接插入排序缩小增量(gap)的操作改进普通的直接插入排序

2.2希尔排序的代码逻辑

将间隔大小为gap(初始值一般为n/2、n/3+1)的数组元素看作一组,每组进行直接插入排序,然后缩小gap(n/2/2、(n/3+1)/3+1),再进行直接插入排序,缩小gap再排序.....

一直到gap为1的直接插入排序完成截止

显然这是循环套循环,因为gap不断缩小而对于每个具体的gap来说又需要进行直接插入排序

2.3希尔排序图解

循环开始,gap初始值为n/2,直接插入排序完成后,gap /= 2,再一次直接插入排序完成后,gap/=2,此时gap缩小至1,此次直接插入排序完成后,数组有序

gap必须缩小至1,才能保证数组有序

gap也可以是 gap = gap / 3 + 1,+1是为了gap最终可缩小至1

gap /= 2不用+1 因为式子本身可以确保gap缩小至1

2.4单单趟排序代码(对于特定的gap的一组元素的排序)

        int gap;int end;int tmp;while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else    break;}a[end + gap] = tmp;}
}

相对于直接插入排序,单单趟的变化简单来说就是移动间隔从1变为了gap

2.5单趟排序代码(对于特定的gap的分组排序)

2.5.1一组排好序再排另一组

int gap;
gap /= 2;
for(int j = 0; j < gap; ++j){for (int i = j; i < n - gap; i += gap){int end = i;int tmp = a[i + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else    break;}a[end + gap] = tmp;}
}

内层for循环控制的是特定的某一组数组元素的end与tmp的变化值

两者间隔为gap,end初始值为i,tmp为其后gap个位置的值,所以i+gap<n,即i < n - gap

因为是先排好一组再排另外一组,所以需要 i+=gap

外层for循环控制的是每一组数组元素的end的初始值 

假设数组一共有n个元素,将间隔大小为gap的数组元素视为一组,那么每一组数组元素的end的初始值 一定 大于等于零小于gap(下标从零开始)

2.5.2 根据元素的所在组进行直接插入排序

int gap;
gap /= 2;
for (int i = 0; i < n - gap; ++i){int end = i;int tmp = a[i + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else    break;}a[end + gap] = tmp;
}

遍历数组元素,根据元素的所在组进行直接插入排序

 for循环控制的是数组元素的end与tmp的变化值

两者间隔为gap,end初始值为i,tmp为其后gap个位置的值,所以i+gap<n,即i < n - gap

通过 ++i 就可实现遍历数组并根据元素的所在组进行直接插入排序的操作

 2.6完整排序代码

2.6.1一组排好序再排另一组

void ShellSortUp2(int* a, int n)
{int gap = n;while (gap > 1){gap /= 2;for(int j = 0; j < gap; ++j){for (int i = j; i < n - gap; i += gap){int end = i;int tmp = a[i + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else    break;}}a[end + gap] = tmp;}}}
}

通过将gap初始化为n,并将gap大于1作为循环结束条件,可以避免单个数的排序现象

再在循环内部将gap/2,也不迟

 2.6.2 根据元素的所在组进行直接插入排序

void ShellSortUp1(int* a, int n)
{int gap = n;while(gap > 1){gap /= 2;for (int i = 0; i < n - gap; ++i){int end = i;int tmp = a[i + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else    break;}a[end + gap] = tmp;}}
}

通过将gap初始化为n,并将gap大于1作为循环结束条件,可以避免单个数的排序现象

再在循环内部将gap/2,也不迟

2.7希尔排序的时间复杂度与空间复杂度

希尔排序的两种实现方式本质上都是分组排序和缩小增量操作,时间复杂度没差别

时间复杂度完整的推导方式小编也无能为力,

只记得结论为时间复杂度为O(N*logN) ,大约是n^1.3

希尔排序的变量个数固定,所进行的操作在原数组上,所以空间复杂度为O(1)

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

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

相关文章

Laravel 后台登录 403 Forbidden 错误深度解决方案-优雅草卓伊凡|泡泡龙

Laravel 后台登录 403 Forbidden 错误深度解决方案-优雅草卓伊凡|泡泡龙一顿操作猛如虎&#xff0c;一看结果250&#xff0c;必须记录&#xff0c;必须记录&#xff0c;&#xff01;今天弄了很久关于我们2023年的产品系统蜻蜓T会议系统专业版&#xff0c;然后终于搞好了密码也重…

Newline全场景方案闪耀2025中国智慧生活大会

7月15日 — 16日&#xff0c;由中国电子视像行业协会等权威机构指导的2025 CIC中国智慧生活大会在京召开。Newline作为视像协会PID分会副会长单位携全场景智慧办公解决方案亮相&#xff0c;首席营销官李宇鹏受邀出席领袖圆桌环节&#xff0c;与腾讯云、京东方、创维、TCL、小猿…

Edge浏览器地址栏默认搜索引擎设置指南

前言 Microsoft Edge 浏览器允许用户自定义地址栏默认搜索引擎&#xff0c;只是设置入口隐藏比较深&#xff0c;以版本 137.0.3296.83 (正式版本) (64 位)为例详细记录设置地址栏默认搜索引擎步骤&#xff1a; Edge 设置默认搜索引擎步骤 通过设置界面修改 打开Edge设置&#x…

Python eval函数详解 - 用法、风险与安全替代方案

Python eval函数详解 - 用法、风险与安全替代方案在Python中&#xff0c;eval() 是一个内置函数&#xff0c;用于解析并执行传入的字符串形式的表达式。它能够将字符串动态地转换为有效的Python代码并运行。虽然 eval() 功能强大&#xff0c;但其使用也伴随着潜在的安全风险。本…

Webpack5 新特性与详细配置指南

一、Webpack5 新特性 内置 Asset Modules&#xff08;资源模块&#xff09; 替代 file-loader、url-loader、raw-loader 等&#xff0c;统一资源处理方式。四种类型&#xff1a;asset/resource&#xff1a;导出文件 URL&#xff08;等同 file-loader&#xff09;。asset/inli…

笼子在寻找一只鸟:解读生活的隐形陷阱

想象一个闪闪发光的笼子&#xff0c;敞开着门&#xff0c;在世界中游荡&#xff0c;寻找一只鸟儿。这画面是不是有点奇怪&#xff1f;这是卡夫卡的格言“一个笼子在寻找一只鸟”带给我们的奇思妙想。通常&#xff0c;鸟儿自由翱翔&#xff0c;笼子静静等待&#xff0c;但卡夫卡…

低空经济展 | 约克科技携小型化测试设备亮相2025深圳eVTOL展

全球低空经济与eVTOL产业盛会——2025深圳eVTOL展&#xff0c;将于2025年9月23日至25日在深圳坪山燕子湖国际会展中心盛大启幕&#xff01; 本届展会以“低空经济eVTOL航空应急救援商载大型无人运输机”为核心&#xff0c;预计汇聚200位发言嘉宾、500家顶尖展商及15,000位专业观…

数学专业转行做大数据容易吗?需要补什么?

高考志愿选择数学专业是一个面向未来的决定。数学作为基础学科&#xff0c;其严谨的逻辑训练和抽象思维能力培养&#xff0c;为后续专业发展提供了广泛的可能性。在数字化时代背景下&#xff0c;数学专业毕业生在数据科学、人工智能等领域的竞争优势明显。大学期间推荐考CDA数据…

物联网系统中-设备管理定义方法

物联网系统中的设备管理是指对联网物理设备进行全生命周期监控、配置、维护和优化的系统性过程。它涵盖了从设备接入到退役的各个环节&#xff0c;是物联网平台的核心能力&#xff0c;确保设备安全、稳定、高效地运行并产生价值。 以下是设备管理的详细定义与核心组成部分&…

java和ptyhon对比

&#x1f4dd; ​1. 语言特性对比​​维度​​Java​​Python​​语法风格​静态类型&#xff0c;需显式声明变量类型&#xff1b;代码冗长&#xff08;需分号、大括号&#xff09;动态类型&#xff0c;变量类型自动推断&#xff1b;简洁&#xff08;缩进代替大括号&#xff0c…

UI测试解决方案TestComplete:助力小团队端到端测试全覆盖

面对软件多平台部署的复杂环境与有限的人力资源&#xff0c;小团队在追求端到端测试覆盖时常常陷入困境&#xff1a;既要确保应用在Windows、macOS、Linux及iOS、Android等碎片化平台上的稳定兼容&#xff0c;又要应对脚本重复编写耗时费力、测试效率低下的挑战&#xff0c;同时…

【Android】事件、绘制坐标系相关

一&#xff0c;事件坐标系即MotionEvent事件下发的坐标系&#xff0c;其坐标轴如下MotionEvent#offsetLocation方法可调整坐标原点&#xff0c;以影响MotionEvent#getX&#xff0c;MotionEvent#getY值&#xff0c;以匹配子View的坐标参考系&#xff0c;进而进行事件处理。注意&…

本地Linux服务器使用Docker快速部署SyncTV

文章目录前言1. Docker部署2. 简单使用演示3. 安装cpolar内网穿透4. 配置公网地址5. 配置固定公网地址前言 当想和异地恋人同步看恐怖片却因网络延迟错过惊悚瞬间&#xff0c;或与朋友组队观看电竞直播时无法实时吐槽…这些尴尬场景或许你都经历过。而SyncTV的存在正是为了解决…

搭建比分网服务器怎么选数据不会卡顿?

一、 体育比分网站的独特技术挑战体育比分网站是互联网服务中的"极限运动"&#xff0c;面临三大技术高峰&#xff1a;数据实时性&#xff1a;NBA最后2分钟的比分延迟超过1秒就会流失用户流量脉冲&#xff1a;欧冠决赛时流量可能是平时的50-100倍全球覆盖&#xff1a;…

7月18日总结

bashupload / upload files from command line 远程文件包含 介绍一个上传文件的网站 bashupload.com 简介 借助bashupload.com&#xff0c;可以简朴地从下令行上传文件&#xff0c;剖析给其他的服务器&#xff0c;桌面和移动装备&#xff0c;最大支持25G。上传的文件会被保留…

【leetcode】3202. 找出有效子序列的最大长度(2)

文章目录题目题解题目 3202. 找出有效子序列的最大长度&#xff08;2&#xff09; 给你一个整数数组 nums 和一个 正 整数 k 。 nums 的一个 子序列 sub 的长度为 x &#xff0c;如果其满足以下条件&#xff0c;则称其为 有效子序列 &#xff1a; (sub[0] sub[1]) % k (su…

Linux内核网络栈深度剖析:inet_connection_sock.c的服务器端套接字管理

引言 在Linux网络协议栈中,net/ipv4/inet_connection_sock.c是实现面向连接协议(如TCP)服务器端逻辑的核心文件。它承载了从端口绑定、连接接受到资源回收的全流程管理,是构建高并发网络服务的基石。本文将深入解析其关键机制和实现原理。 一、地址匹配:端口冲突检测的基…

机器学习中核心评估指标(准确率、精确率、召回率、F1分数)

混淆矩阵混淆矩阵是一个表格&#xff0c;用于总结分类模型在测试集上的预测结果&#xff0c;特别是当真实标签已知时。它将预测结果分为四种情况&#xff08;记忆&#xff1a;实际和预测一致为True&#xff0c;预测为正是Positive&#xff09;&#xff1a;真正例&#xff1a; 实…

从零搭建Cloud Alibaba

1.初始环境的搭建 1.1环境要求&#xff1a; Spring Boot 3.2.5&#xff1a; 基于最新的 Spring Framework 6.x。支持现代化开发模式&#xff0c;帮助开发更加高效。 JDK 17 或更高版本&#xff1a; Spring Boot 3.x 开始要求 Java 17 作为最低运行环境。 Spring Boot 与 Sp…

Spring AI 工具调用

文章目录简述工具定义工具上下文直接返回方法&#xff1a;直接返回工具执行框架控制工具执行用户控制的工具执行异常处理简述 工具调用&#xff08;也称为函数调用&#xff09;是 AI 应用程序中的一种常见模式&#xff0c;允许模型与一组 API 或工具进行交互&#xff0c;从而增…