当前位置: 首页 > news >正文

一篇讲透排序算法之插入排序and选择排序

1.插入排序

1.1算法思想

先将数组的第一个元素当作有序,让其后一个元素与其比较,如果比第一个元素小则互换位置,之后再将前两个元素当作有序的,让第三个元素与前两个元素倒着依次进行比较,如果第三个元素比第二个元素小的话,则交换位置,之后再比较第二个元素和第一个元素。

之后我们重复以上操作即可完成插入排序。

为了帮助大家理解,现在我们一步步完成这些操作。

1.2实现逻辑以及具体实现

首先,如果第二个元素小于第一个元素,则交换位置。

	if (a[1] < a[0]){int tmp = a[1];a[1] = a[0];a[0] = tmp;}

之后,我们就可以让第三个元素依次与前两个元素进行比较了。

在这里,我们要记录一下第二个元素的位置,否则我们不知道如何比较。

因此我们在这里定义一个end来记录第二个元素的位置。

int end = 1;
while (end)
{//如果第三个元素和第二个元素发生了交换//则比较第一个元素和新的第二个元素if (a[end + 1] < a[end]){int tmp = a[end + 1];a[end + 1] = a[end];a[end] = tmp;}//由于前end个元素已经有序,所以有一次没有进if就可以跳出循环了else{break;}end--;
}

现在我们就完成了单趟的循环,但我们需要比较多趟,而每趟的比较中不一样的变量就是end,每趟的比较end都会+1,因此我们在外层再写一个循环即可。

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

到这里我们已经完成了一次插入排序,最后我们只需要将这些内容放在函数定义当中即可彻底完成!

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

2.选择排序

2.1算法思想

先遍历一遍数组,找出最小的元素,然后与第一个元素交换位置。

之后从数组的第二个数开始,再遍历一遍数组,找出此次遍历中最小的数,与第二个数交换位置。

之后重复以上的操作即可完成任务。

使用上述的原理遍历数组,每次遍历都可以选出一个最小的数,放到对应的位置上面去。

2.2实现逻辑以及具体实现

现在我们来逐步实现这个排序算法

首先,我们应遍历数组,找出最小的元素。

int min=a[0];
for (int i = 0; i < n; i++)
{if (a[i] < min){int tmp = min;min = a[i];a[i] = tmp;}
}

我们这样写出现了一个问题,我们交换了min和a[i]的数值,但是a[0]处的数值并没有随着min的改变而改变,对此,我们应该怎么做呢?

这里我们可以将两数交换封装为一个函数,之后我们不再让min记录数值,而是记录下标即可。 

//假设最小的是下标为0处的元素
int min = 0;
for (int i = 0; i < n; i++)
{if (a[i] < a[min]){//交换下标,每次交换后,min中记录的则是较小数的下标//之后进入下一次循环,继续比较min = i;}
}
//比较完毕之后,交换数值即可
swap(&arr[min], &arr[0]);//这个函数自己写,我没贴上来。

现在我们已经找到了最小的数,而且已经将其放到了第一个位置上去。

现在我们只需要在外面再套一层循环,每次不断更新下标,即可完成选择排序。

for (int i = 0; i <n-1; i++)//一共需要比较n-1趟
{//此时i下标元素最小int min = i;for (int j = i+1; j < n; j++)//前i个有序,因此j=i+1,比较n个元素,因此j<n{//假设最小的是下标为j处的元素if (a[j] < a[min]){//交换下标,每次交换后,min中记录的则是较小数的下标//之后进入下一次循环,继续比较min = j;}}//比较完毕之后,交换数值即可swap(&arr[min], &arr[0]);
}

 我们将其封装在函数体内,即可完成一次排序。

void SelectSort(int* arr, int len)
{for (int i = 0; i < len - 1; i++){int min = i;for (int j = i + 1; j < len; j++){if (arr[j] < arr[min]){mini = j;}}swap(&arr[min], &arr[i]);}
}

2.3选择排序的优化

我们的选择排序还可以进行一下优化,我们可以一次循环同时找最小和最大的数据,只需要在每次比较时定义一个min,一个max,即可在一次循环中找到最小和最大的数据。

这里我们还是先完成第一趟排序,代码如下

int max = 0;
int min = 0;
for (int j =1; j < n; j++)//前i个有序,因此j=i+1,比较n个元素,因此j《n
{//假设最小的是下标为j处的元素if (a[j] < a[min]){//交换下标,每次交换后,min中记录的则是较小数的下标min = j;}if (a[j] > a[max]){//交换下标,每次交换后,min中记录的则是较大数的下标max = j;}
}
swap(&arr[min], &arr[0]);
swap(&arr[max], &arr[n-1]);

通过上面这段代码,我相信大家可以了解优化的原理了。

现在我们就可以着手于完成优化后的选择排序了。

由于我们在一个循环体内同时寻找最小值和最大值,并交换位置。

因此我们需要两个变量记录每次循环中最左边的值和最右边的值的下标,我们将其定义为begin和end。

当begin和end相遇时,我们的循环就结束了。这时我们的数组就有序了。

当begin>=end时,她们就有序了。因此我们的循环条件可以写为begin<end。

void SelectSort(int* arr, int len)
{int begin = 0;int end = len - 1;while (begin < end){//假设mini和maxi都是beginint mini = begin;int maxi = begin;for (int i = begin + 1; i <= end; i++){//找大if (arr[mini] > arr[i]){mini = i;}//找小if (arr[maxi] < arr[i]){maxi = i;}}swap(&arr[mini], &arr[begin]);swap(&arr[maxi], &arr[end]);begin++;end--;}}
}

到了这里,我们的选择排序已经基本完成了,

但是请大家思考一个问题: 

如果我们的begin和maxi重合的话,上面这段代码的执行逻辑是什么样的呢?

    如果begin和maxi重合,根据我们的代码逻辑,我们首先会交换mini和begin位置处的值。

此时我们的begin下标处的值已经更新成了mini处的值,而由于我们的maxi和begin是相同的,因此此时我们maxi下标处的值其实是mini处的值。

    文字表述可能比较抽象,我们现在将文字具象化为代码。

		swap(&arr[mini], &arr[begin]);swap(&arr[begin], &arr[end]);

那么应该怎么解决这个问题呢?很简单,因为我们的下标重合了,因此我们在进行完第一个交换之后更新一下maxi的值即可。

void SelectSort(int* arr, int len)
{int begin = 0;int end = len - 1;while (begin < end){//假设mini和maxi都是beginint mini = begin;int maxi = begin;for (int i = begin + 1; i <= end; i++){//找大if (arr[mini] > arr[i]){mini = i;}//找小if (arr[maxi] < arr[i]){maxi = i;}}swap(&arr[mini], &arr[begin]);//begin处的值和mini处的值交换了位置//因此现在mini处保存的值为最大值//我们将maxi更新为mini即可。if (begin == maxi){maxi = mini;}swap(&arr[maxi], &arr[end]);begin++;end--;}}
}

相关文章:

一篇讲透排序算法之插入排序and选择排序

1.插入排序 1.1算法思想 先将数组的第一个元素当作有序&#xff0c;让其后一个元素与其比较&#xff0c;如果比第一个元素小则互换位置&#xff0c;之后再将前两个元素当作有序的&#xff0c;让第三个元素与前两个元素倒着依次进行比较&#xff0c;如果第三个元素比第二个元素…...

CompletableFuture的主要用途是什么?

CompletableFuture 的主要用途是为复杂的异步编程模型提供一种更简单&#xff0c;更具可读性的方式。它主要用于以下几个方面&#xff1a; 非阻塞计算&#xff1a;CompletableFuture 为处理高延迟的计算任务提供了非阻塞的解决方案。你可以启动一个计算任务&#xff0c;而不需要…...

QtCreator,动态曲线实例

样式图&#xff1a; .ui 在sloem1.ui文件中&#xff0c;拖入一个label控件&#xff0c; 头文件.h #include "QtGui/QPainter.h" #include "QtCore/QTimer.h"protected:bool eventFilter(QObject *obj,QEvent *event);void labelPaint();public slots: /…...

Model-Based Pose Estimation for Rigid Objects(基于SIFT)

6D目标检测工程落地需求的小算力算法&#xff0c;本文具有借鉴意义&#xff0c;但对于特征点少的目标不太好用。 摘要 在多个实际应用中&#xff0c;经常会遇到确定图像中出现的物体姿态的问题。处理这一挑战的最有效策略是按照基于模型的范式进行&#xff0c;这涉及构建物体…...

STM32自己从零开始实操02:输入部分原理图

一、触摸按键 1.1指路 项目需求&#xff1a; 4个触摸按键&#xff0c;主控芯片 TTP224N-BSBN&#xff08;嘉立创&#xff0c;封装 TSSOP-16&#xff09;&#xff0c;接入到 STM32 的 PE0&#xff0c;PE1&#xff0c;PE2&#xff0c;PE3。 1.2走路 1.2.1数据手册重要信息提…...

JavaScript异步编程——03-Ajax传输json和XML的技术文档

JavaScript异步编程——03-Ajax传输json和XML的技术文档 目录 JavaScript异步编程——03-Ajax传输json和XML的技术文档 一、引言 二、Ajax简介 三、Ajax传输JSON数据 四、Ajax传输XML数据 五、总结 一、引言 在现代Web开发中&#xff0c;Ajax技术已经成为实现前后端数据交…...

移动端常用meta

在移动端开发中&#xff0c;<meta> 标签用于提供关于HTML文档的元数据&#xff0c;这些元数据不会显示在页面上&#xff0c;但可以被浏览器解析&#xff0c;用于控制页面的行为和外观。以下是一些在移动端开发中常用的 标签&#xff1a; 1. 视口设置 这是移动端开发中最…...

C++_C++11的学习

1. 统一的列表初始化 1.1&#xff5b;&#xff5d;初始化 在C98 中&#xff0c;标准就已经允许使用花括号 {} 对数组或者结构体元素进行统一的列表初始值设定。而到了C11&#xff0c;标准扩大了用大括号括起的列表 ( 初始化列表 )的使用范围&#xff0c;使其能适用于所有的内…...

RAC11G参数修改错误导致启库失败处理

问题描述 部署完一套3节点的11g RAC后&#xff0c;进行了内存的参数优化&#xff0c;优化时忘记了先备份参数文件&#xff0c;忘记了计算内存参数眼盲的复制粘贴执行内存优化sql导致优化后重启实例启动失败。艾&#xff0c;由于粗心自己给自己挖了个坑。 切记更改参数步骤&am…...

UE4打包Win64项目命令行

仅用于个人记录&#xff0c;写的粗糙&#xff0c;勿喷 BuildProject.bat 具体命名参数请参照UE引擎RunUAT源码&#xff08;Programs\AutomationTool下Program.cs&#xff09; 参数1&#xff1a;引擎安装路径 参数2&#xff1a;uproject路径 参数3&#xff1a;输出路径 参数…...

c语言bug汇总中篇5

40. 不关注代码风格一致性 代码风格一致性有助于提高代码的可读性和可维护性。如果团队成员使用不同的代码风格&#xff0c;会导致代码看起来杂乱无章&#xff0c;增加阅读和理解的成本。 为了保持代码风格的一致性&#xff0c;程序员应该&#xff1a; - 遵循团队或项目约定的…...

【linux】进程(一)

1. 冯诺依曼体系结构 计算机基本都遵循着冯诺依曼体系 我们使用的计算器是由一个个硬件构成的&#xff1a; 中央控制器&#xff08;CPU&#xff09; &#xff1a; 运算器 控制器 等输入设备 : 键盘&#xff0c;鼠标&#xff0c;网卡 等输出设备 : 显示器&#xff0c;网卡 等…...

手把手教你用Python轻松玩转SQL注入

一、浅谈SQL注入 SQL注入其实就是把SQL命令插入到WEB表单中提交或者输入一些页面请求的查询字符串&#xff0c;比如我们输网址&#xff0c;就是相当于这种操作&#xff0c;只不过我们不是在测试SQL注入漏洞&#xff0c;而仅仅只是为了输入后看到相应网页上的内容而已。一般方法…...

redis的几种部署模式及注意事项

Redis 可以以多种部署模式来满足不同的需求&#xff0c;其中一些常见的部署模式包括&#xff1a;单节点部署、主从复制部署、哨兵模式部署和集群部署。这些部署模式各有特点&#xff0c;适用于不同的场景和需求&#xff1a; 概念 单节点部署&#xff1a; 特点&#xff1a;单…...

使用Python生成一束玫瑰花

520到了&#xff0c;没时间买花&#xff1f;我们来生成一个电子的。 Python不仅是一种强大的编程语言&#xff0c;用于开发应用程序和分析数据&#xff0c;它也可以用来创造美丽的艺术作品。在这篇博客中&#xff0c;我们将探索如何使用Python生成一束玫瑰花的图像。 准备工作…...

紫光同创PGL22G开发板|盘古22K开发板,国产FPGA开发板,接口丰富

盘古22K开发板是基于紫光同创Logos系列PGL22G芯片设计的一款FPGA开发板&#xff0c;全面实现国产化方案&#xff0c;板载资源丰富&#xff0c;高容量、高带宽&#xff0c;外围接口丰富&#xff0c;不仅适用于高校教学&#xff0c;还可以用于实验项目、项目开发&#xff0c;一板…...

大模型的实践应用24-LLaMA-Factory微调通义千问qwen1.5-1.8B模型的实例

大家好,我是微学AI,今天给大家介绍一下大模型的实践应用24-LLaMA-Factory微调通义千问qwen1.5-1.8B模型的实例, LLaMA-Factory是一个专门用于大语言模型微调的框架,它支持多种微调方法,如LoRA、QLoRA等,并提供了丰富的数据集和预训练模型,便于用户进行模型微调。通义千问…...

力扣爆刷第142天之二叉树五连刷(构造树、搜索树)

力扣爆刷第142天之二叉树五连刷&#xff08;构造树、搜索树&#xff09; 文章目录 力扣爆刷第142天之二叉树五连刷&#xff08;构造树、搜索树&#xff09;一、106. 从中序与后序遍历序列构造二叉树二、654. 最大二叉树三、617. 合并二叉树四、700. 二叉搜索树中的搜索五、98. …...

0407放大电路的频率响应

放大电路的频率响应 单时间常数RC电路的频率响应中频响应高频响应低频响应全频域响应 放大电路频率响应概述1. 直接耦合放大电路频域响应阻容耦合放大电路频域响应 4.7.1 单时间常数RC电路的频率响应 4.7.2 放大电路频率响应概述 4.7.3 单级共射极放大电路的频率响应 4.7.4 单级…...

数据分析必备:一步步教你如何用Pandas做数据分析(6)

1、Pandas 函数应用 Pandas 重建索引操作实例 要将您自己或其他库的函数应用于Pandas对象&#xff0c;您应该了解三个重要的方法。方法如下所述。要使用的适当方法取决于您的函数是希望对整个数据帧进行操作&#xff0c;还是行操作还是按列操作&#xff0c;还是按元素操作。 表…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...