排序【插入排序】

排序的概念

排序:所谓排序,就是将一份数据,通过某个或者某些关键字的大小,进行递增或者递减排序的操作。

稳定性:假定在待排序的数据组中,存在多个相同的元素,若经过排序,这些数据之间的相对位置应保持不变。例如:在原数组中,a[i]=a[j],并且a[i]的位置在a[j]之前,如果这个数组被进行了排序操作,且a[i]仍然在a[j]之前(a[i]a[j]的位置可能会被改变,但是他们之间的位置关系不会改变),那么这个排序算法就是稳定的,反之就是不稳定。

内部排序:数据元素全部在内存中的排序。

外部排序:由于数据元素太多,不能同时放在内存中,根据排序过程的需求,不断地在内外存之间移动数据的排序。

常见的算法排序

在这里插入图片描述

插入排序算法的实现

基本思想

直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的元素根据其元素的大小逐个插入到一个已经排好序的有序序列中,所有元素插入完为止,这样就得到一个新的有序序列。

就是将待排序元素之前的数组当作已经有序的数组,再将待排元素与数组内的元素进行比较。

在我们玩扑克牌的时候,就在无意中使用了插入排序的思想在这里插入图片描述

直接插入排序:

当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序了,这时候用array[i]与array[i-1],array[i-2],…进行比较,找到插入位置,就将array[i]插入,原来位置上的元素顺序后移,如图在这里插入图片描述
直接插入排序的总结:

  1. 元素集合越接近有序,直接插入排序算法就越快
  2. 时间复杂度为 O ( N 2 ) O(N^2) O(N2)
  3. 空间复杂度为 O ( 1 ) O(1) O(1),它是一种稳定的排序算法

代码

#include<stdio.h>void InsertSort(int* a, int n)
{for (int i = 0; i < n - 1; i++){//[0, end]有序,将end+1位置的值插入到[0, end]里面去,并保持有序int end = i;int tmp = a[end + 1];while (end >= 0){if (tmp < a[end]){a[end + 1] = a[end];end--;}else{break;}}//这个代码在这里可以同时解决俩个情况// 情况一:tmp在遍历的时候发现了比他更小的值// 情况二:遍历了一边数组,并没有发现比tmp更小的数(end < 0)a[end + 1] = tmp;}
}void PrintArray(int* a, int n)
{for (int i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");
}void TestInsertSort()
{int a[] = { 9,8,6,4,2,1,0,5,7,3 };InsertSort(a,sizeof(a)/sizeof(a[0]));PrintArray(a, sizeof(a) / sizeof(a[0]));}

在这里插入图片描述

直接插入排序遇到逆序数组就会很慢了,这时就有个叫希尔的人对直接插入排序进行了优化,这使得排序效率大大提升了。

希尔排序

希尔排序在排序之前会进行预排序,让数组接近有序,然后再使用直接插入排序。
在这里插入图片描述
上图为案例

我将数据分割成多个组,间隙为gap个(并不是在物理上分成多个数组,而是逻辑上将他们分组)。

假设gap为3,那么在分组中元素9的下一个元素为5,再下一个元素为8,最后一个元素为5,逻辑上这个数组就为[9,5,8,5]
逻辑上以1开头的数组为[1,7,6],以2开头的数组为[2,4,3]
在这里插入图片描述
但是他们实际位置并没有改变,我们也没有开辟新空间来存放数据
我们分好组后,对每组元素进行插入排序,就是分别对[9,5,8,5][1,7,6]2,4,3进行内部的插入排序
在这里插入图片描述
经过预排序后原数组[9,1,2,5,7,4,8,6,3,5]变成了[5,1,2,5,6,3,8,7,4,9]

预排序并没有将整个数组变成有序,而是将每个间隙为gap的数组变成了有序(我们使用还是直接插入排序,只不过元素与元素之间的间隔不是 1,而是gap)。

虽然预排序没有直接的将整个数组排好序,但是他能很快速的将较大的元素往后放,把较小的数据往前放(案例数组经过预排序后,最后的三个数据就是每组最大的元素)

单组排序

我们先来红色这一组([9,5,8,5]

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

在这里插入图片描述
排序后正如我们所想的一样,[9,5,8,5]这一组已经有序了。

接下来就是从单组排序拓展到多组排序了

单组排序到多组排序

有两种方法

  1. 在外面再套一层循环(每组分开排序)
void ShellSort(int* a, int n)
{int gap = 3;for (int j = 0; j < gap; j++)//j确定起始位置{for (int i = 0; i < n - gap; i += gap){int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}}

效果:
在这里插入图片描述

  1. 多组并在一起排序
    改动也很简答,将for (int i = 0; i < n - gap; i += gap)改成for (int i = 0; i < n - gap; i++)
void ShellSort(int* a, int n)
{int gap = 3;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{break;}}a[end + gap] = tmp;}}

效果:
在这里插入图片描述

他们的效率是一样,只不过第二种方法更美观。

接下来就是改变gap的大小了。

改变gap并完成排序

gap大与小的区别

  • gap越大,大的数可以越快的跳到后面,小的数可以越小的跳到前面,但是预排序完了也越不接近有序。
  • gap越小,跳的越慢,但是也越接近有序;当gap等于1,就相当于直接插入排序了。

当gap等于1,那么这个数组就有序了。

那么这个gap该怎么变呢,其实到现在都没有一个准确的最优方法。

我们当前最合适的方法是 gap/3,但是为了避免gap=0,我们在后面+1也就是gap = gap / 3 + 1;

当gap>1时,是预排序,当gap==1时,是直接插入排序,并不是先通过一个函数完成预排序再通过另一个函数完成直接插入排序。

void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;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{break;}}a[end + gap] = tmp;}}}

在这里插入图片描述
完整代码:

void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;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{break;}}a[end + gap] = tmp;}printf("gap=%2d:->", gap);PrintArray(a, n);}}
void TestShellSort()
{int a[] = { 9,1,2,5,7,4,8,6,3,5 };printf("排序前:");PrintArray(a, sizeof(a) / sizeof(a[0]));ShellSort(a, sizeof(a) / sizeof(a[0]));printf("排序后:");PrintArray(a, sizeof(a) / sizeof(a[0]));
}int main()
{TestShellSort();return 0;
}

结语

最后感谢您能阅读完此片文章,如果有任何建议或纠正欢迎在评论区留言,也可以前往我的主页看更多好文哦(点击此处跳转到主页)。
如果您认为这篇文章对您有所收获,点一个小小的赞就是我创作的巨大动力,谢谢!!!

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

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

相关文章

决定佛蒙特州版图的关键历史事件:

​决定佛蒙特州版图的关键历史事件: 1. 早期探险与命名&#xff1a; - 1609年&#xff0c;法国探险家萨缪尔德尚普兰&#xff08;Samuel de Champlain&#xff09;到达了现在的佛蒙特州区域&#xff0c;并探索了尚普兰湖&#xff08;Lake Champlain&#xff09;。他将周围的山…

TS_类型

目录 1.类型注解 2.类型检查 3.类型推断 4.类型断言 ①尖括号&#xff08;<>&#xff09;语法 ②as语法 5.数据类型 ①boolean ②number ③string ④undefined 和 null ⑤数组和元组 ⑥枚举 ⑦any 和void ⑧symbol ⑨Function ⑩Object 和 object 6.高…

ATL新能源科技薪资待遇及Verify测评语言理解数字推理题型简介

一、走进ATL新能源科技 ATL新能源公司&#xff0c;即东莞新能源科技有限公司&#xff0c;是全球领先的可充式锂离子电池研发、生产和营销企业。成立于2004年&#xff0c;总部位于香港&#xff0c;产品广泛应用于消费电子产品和电动汽车领域。ATL以其技术创新和与苹果等大客户的…

2024年【电工(初级)】考试内容及电工(初级)模拟考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 电工&#xff08;初级&#xff09;考试内容参考答案及电工&#xff08;初级&#xff09;考试试题解析是安全生产模拟考试一点通题库老师及电工&#xff08;初级&#xff09;操作证已考过的学员汇总&#xff0c;相对有…

等保2.0安全计算环境解读

等保2.0&#xff0c;即网络安全等级保护2.0制度&#xff0c;是中国为了适应信息技术的快速发展和安全威胁的新变化而推出的网络安全保护标准。相较于等保1.0&#xff0c;等保2.0更加强调主动防御、动态防御和全面审计&#xff0c;旨在实现对各类信息系统的全面保护。 安全计算环…

Docker基础知识的掌握,相关基本命令的用法

安装docker步骤&#xff1a;https://b11et3un53m.feishu.cn/wiki/Rfocw7ctXij2RBkShcucLZbrn2d 1.docker Docker 是一种容器化平台&#xff0c;用于帮助开发者打包、发布和管理应用程序及其依赖关系。通过 Docker&#xff0c;开发者可以将应用程序及其所有依赖项打包到一个称为…

『MySQL 实战 45 讲』22 - MySQL 有哪些“饮鸩止渴”提高性能的方法?

MySQL 有哪些“饮鸩止渴”提高性能的方法&#xff1f; 需求&#xff1a;业务高峰期&#xff0c;生产环境的 MySQL 压力太大&#xff0c;没法正常响应&#xff0c;需要短期内、临时性地提升一些性能 短连接风暴 短连接模式&#xff1a;执行很少的 SQL 语句就断开&#xff0c;…

uniapp加载打点点效果

uniapp加载打点点效果 背景实现思路代码实现尾巴 背景 为了增加系统的交互性&#xff0c;我们在加载数据时通常会增加一些loading动效&#xff0c;但是在某些场景下只需要一些简单文字提醒。比如说使用【加载中】或者【loading】等字段&#xff0c;但是写静态的字符又显得交互…

【若依前后端分离】前端vue页面查看服务器本地的PDF

后端实现&#xff1a; 使用FileSystemResource包装文件&#xff0c;以便Spring MVC可以处理该资源 创建HttpHeaders对象以设置响应头 设置Content-Disposition头&#xff0c;使得浏览器以内联方式显示PDF&#xff08;即在浏览器中直接打开&#xff09; 设置Content-Type为appli…

Thinger.io 支持多协议、插件化100%开源 IoT 企业级物联网平台

项目源码&#xff0c;文末联系小编 Thinger.io 是一个开源插件化物联网平台&#xff0c;提供了设备原型、扩展和设备连接管理所需的一切工具。我们的目标是使物联网的使用民主化&#xff0c;使其可供全世界使用&#xff0c;并简化大型物联网项目的开发。 01 Thinger.io 物联网平…

Python学习路线图:120天系统学习,你也能成大神!

学Python&#xff0c;切忌今天这学一点&#xff0c;明天那里学一点&#xff0c;零零散散没有系统的学习。这样不仅耽搁大家时间&#xff0c;久而久之也会消磨大家学习的兴致&#xff01;这里给大家总结了一张系统的Python学习路线图&#xff01;希望大家共勉&#xff01; Pyth…

期末考试结束,成绩如何快速发布?

随着期末考试的落幕&#xff0c;老师们又迎来了一项繁琐的任务将成绩单私信给学生家长。这项工作耗时耗力&#xff0c;而且极易出错&#xff0c;期末老师的工作已经足够繁重还要私发成绩&#xff0c;简直是雪上加霜。 好消息是&#xff0c;现在有了易查分小程序&#xff0c;只需…

学会整理电脑,基于小白用户(无关硬件升级)

如果你不想进行硬件升级&#xff0c;就要学会进行整理维护电脑 基于小白用户&#xff0c;每一个操作点我都会在后续整理出流程&#xff0c;软件推荐会选择占用小且实用的软件 主要从三个角度去讨论【如果有新的内容我会随时修改&#xff0c;也希望有补充告诉我&#xff0c;我…

【Linux详解】进程地址空间

目录 研究背景 验证地址空间 实验一&#xff1a;父子进程变量地址一致性 实验二&#xff1a;变量值修改后父子进程的差异 分析与结论 实验三&#xff1a;进程地址空间验证 理解进程地址空间 区域与页表 写时拷贝机制 进程地址空间的意义 文章手稿&#xff1a; xmind…

基于语音识别的智能电子病历(二)苹果端的语音接入

是2011年参与的&#xff0c;俺负责Wav文件处理、FTP通讯和一些后端部分。iPhone/iPad/iPod Recorder 前2年还在APP Store上 说明 Step-by-Step Procedure to Install App and Use the FnetRecorder Download the App from Apple Store Launch Apple Store and key in “fnetr…

labview排错

源代码正常跑&#xff0c;应用程序报这个错&#xff0c;是因为源代码的可以找到项目路径内所有dll的路径&#xff0c;而应用程序只能找到data文件夹的dll文件 解决查看源代码中.net的程序集的路径&#xff0c;复制对应的dll到data文件夹下 在执行developinterface.dll出现labv…

Python+Pytest+Allure+Yaml+Jenkins+GitLab接口自动化测试框架详解

PythonPytestAllureYaml接口自动化测试框架详解 编撰人&#xff1a;CesareCheung 更新时间&#xff1a;2024.06.20 一、技术栈 PythonPytestAllureYamlJenkinsGitLab 版本要求&#xff1a;Python3.7.0,Pytest7.4.4,Allure2.18.1,PyYaml6.0 二、环境配置 安装python3.7&…

Python operator模块这么用,效率杠杠的!

目录 1、基础操作符应用 🐍 1.1 加载operator模块 1.2 使用itemgetter进行排序 1.3 attrgetter与方法调用 2、高级功能探索 🔍 2.1 methodcaller的妙用 2.2 操作符重载与定制 3、结合lambda表达式 ✨ 3.1 lambda与operator模块协同工作 3.2 实战案例分析 4、结合…

如何保护磁盘数据?电脑磁盘数据怎么保护?

电脑磁盘是存储数据的基础&#xff0c;可以将各种重要数据保存在其中。为了避免数据泄露&#xff0c;我们需要保护磁盘数据。那么&#xff0c;电脑磁盘数据怎么保护呢&#xff1f;下面我们就一起来了解一下吧。 文件夹加密超级大师 文件夹加密超级大师是一款优秀的电脑数据加密…

人工智能 (AI) 基本概念 入门篇【C#】版

1. 什么是人工智能&#xff1f; 人工智能&#xff08;Artificial Intelligence, AI&#xff09;是指计算机系统能够执行通常需要人类智能的任务&#xff0c;如视觉识别、语音识别、决策和语言翻译等。AI的核心是通过算法和数据进行学习和推理&#xff0c;以实现智能行为。 2.…