排序算法2:直接选择排序与快速排序

目录

1.直接选择排序

1.1直接选择排序的优化

2.快速排序

2.1基准值的置位(Hoare版)

 2.2挖坑法

2.3lomuto前后指针


前言

前面我们进入了排序算的讲解。今天我们将继续学习几种重要的排序思想,好,咱们三连上车开始今天的内容。

1.直接选择排序

在元素的集合中选出最大值(最小值),存放在序列的起始位置,直到全部的待排序位置数据排完

  1. 在元素集合中arr[i]-----arr[n-1]中选择值最大(小)数据
  2. 若他不是这组元素中的最后一个数据,则将他与这组的最后一个元素交换。
  3. 在剩余的arr[i]----arr[n-2](arr[i + 1]-----arr[n-1])的集合中,传重复上面的步骤,直到集合剩余最后一个元素! 

 思路十分的简单,我们按照这样的思想来实现一下代码:

void SelectSort1(int* arr, int sz)
{for (int i = 0; i < sz; i++){int begin = i;int min = begin;for (int j = begin + 1; j < sz; j++){if (arr[min] > arr[j]){min = j;}}Swap(&arr[min], &arr[begin]);}
}

 

 我们这样就实现了排序的目的,但是大家也不难看出,直接这样的排序跟冒泡排序相差无几,同样的效率低下,想要扩大他的使用场景,就要将他进行进一步的优化。

1.1直接选择排序的优化

原来的直接选择排序在排序时只是将特定范围内的最小值与该范围内的第一个元素进行交换,那如果我们在寻找最小值的同时,也来寻找最大值来与最后面的元素进行交换,这样就可以大幅提高排序的效率了。

按照这个思路我们来实现这个代码:

void SelectSort(int* arr, int sz)
{int begin = 0;int end = sz - 1;while (end > begin){int min = begin;int max = begin;//找特定范围中最小的值和最大值for (int j = begin + 1; j <= end; j++){if (arr[min] > arr[j])min = j;if (arr[max] < arr[j])max = j;}//避免max与begin都在同一位置,begin和min进行交换后,max数据变成了最小的数据if (max == begin){max = min;}Swap(&arr[min], &arr[begin]);Swap(&arr[max], &arr[end]);end--;begin++;}
}

直接选择牌序的优化就完成了!! 

2.快速排序

 快熟排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本的思想就是:任取待排序的元素序列中的某个元素作为基准值,按照排序码将待排序的集合分割为两个子序列,左子序列中所有元素都要小于基准值,有序列中的元素都大于基准值,然后在左右子序列种重复该过程,直到左右的元素排列到相应的位置为止。

2.1基准值的置位(Hoare版)

这里我们单独创建一个函数来查找排序区域的基准值位置:

int FindKey(int* arr, int left, int right)
{//从左边找比基准值大的数据//从右边找基准值较小的数据int key = left;left++;while (left <= right){while (left <= right&&arr[left] < arr[key]){left++;}while (left <= right && arr[right] > arr[key]){right--;}if (left <= right)Swap(&arr[right--], &arr[left++]);//在遇到一定区域内的值都相等时,需要让基准值的位置向中间移,这样才能让区域越划越小}Swap(&arr[key], &arr[right]);return right;
}

找到基准值后,我们根据二叉树结构的性质,很容易就能够确定使用递归的思想来实现循环划分左右子区域的操作

void QuickSort(int* arr, int left, int right)
{if (left >= right)return;//left and right----->找基准值mid//1.如何找基准值int keyi = FindKey(arr, left, right);//左子序列QuickSort(arr, left, keyi - 1);//右子序列QuickSort(arr, keyi + 1, right );
}

 所以Hoare版的快速排序我们就完成了,接下来我们来验证一下:

int FindKey(int* arr, int left, int right)
{//从左边找比基准值大的数据//从右边找基准值较小的数据int key = left;left++;while (left <= right){while (left <= right&&arr[left] < arr[key]){left++;}while (left <= right && arr[right] > arr[key]){right--;}if (left <= right)Swap(&arr[right--], &arr[left++]);//在遇到一定区域内的值都相等时,需要让基准值的位置向中间移,这样才能让区域越划越小}Swap(&arr[key], &arr[right]);return right;
}
void QuickSort(int* arr, int left, int right)
{if (left >= right)return;//left and right----->找基准值mid//1.如何找基准值int keyi = FindKey(arr, left, right);//左子序列QuickSort(arr, left, keyi - 1);//右子序列QuickSort(arr, keyi + 1, right );
}

 

快速排序在实际的生活工作场景中运用广泛,这得益于他二叉树的结构性质,使其拥有了与堆排序相近甚至更快的速率。 

 2.2挖坑法

思路:创建左右指针。首先从右向左找比基准值小的数据,找到后立即放入左边的坑位,当前位置变为新的“坑”, 然后从左向右找比基准值大的数据,找到后立即放入右边的坑洞中,当前位置变为新的坑,结束循环后将最开始存储的分界值放入当前的“坑”中,返回当前“坑”的下标(即分界值下标)。

 挖坑法相较于Hoare的方法要简单,我们稍加理解就可以将代码写出来。

我们来看代码:

int _QuickSort(int* a, int left, int right)
{int mid = a[left];int hole = left;int key = a[hole];while (left < right){while (left < right && a[right] >= key){--right;}a[hole] = a[right];hole = right;while (left < right && a[left] <= key){++left;}a[hole] = a[left];hole = left;}a[hole] = key;return hole;
}

本质上这时一种新的找基准值的方法,虽然相较于Hoare版的代码挖坑法的代码会更加的冗余,但是他的思想和实现方法更易于理解。

int _QuickSort(int* a, int left, int right)
{int mid = a[left];int hole = left;int key = a[hole];while (left < right){while (left < right && a[right] >= key){--right;}a[hole] = a[right];hole = right;while (left < right && a[left] <= key){++left;}a[hole] = a[left];hole = left;}a[hole] = key;return hole;
}
void QuickSort(int* arr, int left, int right)
{if (left >= right)return;//left and right----->找基准值mid//1.如何找基准值int keyi = _QuickSort(arr, left, right);//左子序列QuickSort(arr, left, keyi - 1);//右子序列QuickSort(arr, keyi + 1, right );
}

 

经过验证,我们的代码就实现了! 

2.3lomuto前后指针

创建前后指针,从左往右找比基准值小的进行交换,使得小的数据都排在基准值的左边。

 

前后指针法相比于前面的挖坑法和Hoare方法都要简单,但是思路着实不好想,这就需要我们积累新的方法了:

  • 定义两个指针 prev和cur;
  •  cur指向的位置的数据跟key的值比较;
  • 若arr[cur] < arr[key],prev向后走一步并和cur交换;
  • 若arr[cur] >= arr[key],cur继续向后
int Doublelomuto(int *arr, int left, int right)
{int prev = left, cur = left;int key = left;while (cur <= right){if (arr[cur] < arr[key] && ++prev != cur){Swap(&arr[prev], &arr[cur]);}cur++;}Swap(&arr[key], &arr[prev]);return prev;
}

最后我们来验证一下这个代码:

int Doublelomuto(int *arr, int left, int right)
{int prev = left, cur = left;int key = left;while (cur <= right){if (arr[cur] < arr[key] && ++prev != cur){Swap(&arr[prev], &arr[cur]);}cur++;}Swap(&arr[key], &arr[prev]);return prev;
}
void QuickSort(int* arr, int left, int right)
{if (left >= right)return;//left and right----->找基准值mid//1.如何找基准值int keyi = Doublelomuto(arr, left, right);//左子序列QuickSort(arr, left, keyi - 1);//右子序列QuickSort(arr, keyi + 1, right );
}

快速排序的三种版本的递归排序方法就实现完了。

好今天的学习就到这里,我们下期再见,拜拜!! 

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

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

相关文章

ChatTTS文本转语音本地部署结合内网穿透实现远程使用生成AI音频

文章目录 前言1. 下载运行ChatTTS模型2. 安装Cpolar工具3. 实现公网访问4. 配置ChatTTS固定公网地址 前言 本篇文章主要介绍如何快速地在Windows系统电脑中本地部署ChatTTS开源文本转语音项目&#xff0c;并且我们还可以结合Cpolar内网穿透工具创建公网地址&#xff0c;随时随…

动态规划.

目录 &#xff08;一&#xff09;递归到动规的一般转化方法 &#xff08;二&#xff09;动规解题的一般思路 1. 将原问题分解为子问题 2. 确定状态 3. 确定一些初始状态&#xff08;边界状态&#xff09;的值 4. 确定状态转移方程 &#xff08;三&#xff09;能用动规解…

【网络】HTTP协议

目录 概述 URL 结构 urlencode&#xff08;URL编码&#xff09; urldecode&#xff08;URL解码&#xff09; 工具网址 HTTP请求 请求行 请求头 请求体 HTTP响应 状态行 响应头 响应体 个人主页&#xff1a;东洛的克莱斯韦克-CSDN博客 概述 HTTP协议是应用层协议…

TCP 三次握手建立连接

一开始&#xff0c;客户端和服务端都处于 CLOSE 状态。先是服务端主动监听某个端口&#xff0c;处于 LISTEN 状态 1. 第一次握手 客户端会随机初始化序号&#xff08;client_isn&#xff09;&#xff0c;将此序号置于 TCP 首部的「序号」字段中&#xff0c;同时把 SYN 标志位置…

略读ArrayList源码

ArrayList是Java集合框架中的一部分&#xff0c;底层是通过数组实现的&#xff0c;可以动态增长和缩减。 一、首先看成员变量 序列化ID定义。在Java中&#xff0c;如果一个类实现了Serializable接口&#xff0c;那么它的serialVersionUID就非常重要了。serialVersionUID用于确…

python 图片爬虫记录

感谢大家的点赞。再补充一点。 对于这个 url https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEqB5nighYsMZE7kexaVNJfxy3OkRutNEKatksw9u5f-ckHNROLzFyx2Uty3zYWNEaeOmzsljGr3eARiDWaM9DM8G2hPuPf8uZP0NO3kNUCnM2Cjb3ZKtLhJDBwqeR4ElpJ7ID5_wIHGQ/s200 这个url最…

Python进阶 JSON数据,pyecharts制图

目录 json数据格式的转换 什么是json json本质 注意 pyecharts快速入门 画一个最简单的折线图 使用全局配置选项优化折线图 总结 json数据格式的转换 什么是json 一种轻量级的数据交换格式&#xff0c;可以按json指定的格式去组织和封装数据 json本质 带有特定格式的…

汇川技术|Inoproshop基本使用方法:汇川指令库、库文件

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 本节熟悉了解汇川常用指令库的分类及概述&#xff0c;了解Inoproshop库文件&#xff1b; 以下为学习笔记。 01 指令简介与分类 可编程控制系统中&#xff0c;使CPU完成某种操作或实现某种功能的命令及多个命令的组合…

CCRC-DSA数据安全评估师:加快构建大网络安全工作格局

7月31日&#xff0c;第十二届ISC.AI互联网安全大会开幕式在北京国家会议中心隆重举行&#xff0c;本次大会以“构建大型安全防护模型&#xff0c;引领安全产业创新”为主题。 中央网络安全和信息化委员会办公室副主任、国家互联网信息办公室副主任王京涛出席并发表了重要讲话。…

语音平台调研

百度DuerOS开放平台 DuerOS是百度推出的对话式人工智能操作系统&#xff0c;即智能语音交互平台。DuerOS的技术架构包含“对话服务”和“技能框架”两大基础协议。两大协议连通起来的对话核心系统、智能设备开放平台和技能开放平台&#xff0c;构成了完整DuerOS的智能生态系统。…

C#初级——字典Dictionary

字典 字典是C#中的一种集合&#xff0c;它存储键值对&#xff0c;并且每个键与一个值相关联。 创建字典 Dictionary<键的类型, 值的类型> 字典名字 new Dictionary<键的类型, 值的类型>(); Dictionary<int, string> dicStudent new Dictionary<int, str…

Javascript常见算法(二)【学习】

动态规划 斐波那契数列&#xff1a; 经典的动态规划问题&#xff0c;每个数是前两个数的和。 斐波那契数列&#xff08;Fibonacci sequence&#xff09;是一个非常著名的数列&#xff0c;其中每个数是前两个数的和&#xff0c;序列以0和1开始。在JavaScript中&#xff0c;有多…

药厂子母钟系统,强抗干扰能力,满足复杂生产环境

在制药行业中&#xff0c;精确的时间同步对于确保药品生产的质量和合规性至关重要。药厂子母钟系统作为一种高度可靠的时间同步解决方案&#xff0c;不仅能够提供准确的时间信息&#xff0c;还具有强大的抗干扰能力&#xff0c;非常适合在复杂的生产环境中使用。本文将详细介绍…

[STM32]HAL库实现自己的BootLoader-BootLoader与OTA-STM32CUBEMX

目录 一、前言 二、BootLoader 三、BootLoader的实现 四、APP程序 五、效果展示 六、拓展 一、前言 听到BootLoader大家一定很熟悉&#xff0c;在很多常见的系统中都会存在BootLoader。本文将介绍BootLoader的含义和简易实现&#xff0c;建议大家学习前掌握些原理基础。 …

YOLOV8替换Lion优化器

YOLOV8替换Lion优化器 1 优化器介绍博客 参考bilibili讲解视频 论文地址&#xff1a;https://arxiv.org/abs/2302.06675 代码地址&#xff1a;https://github.com/google/automl/blob/master/lion/lion_pytorch.py """PyTorch implementation of the Lion …

C++初学(11)

不知不觉就第11篇了QWQ 11.1、指针和自由存储空间 之前提到了计算机程序在存储数据时必须跟踪的3个基本属性&#xff1a; &#xff08;1&#xff09;信息存储在何处&#xff1b; &#xff08;2&#xff09;存储的值为多少&#xff1b; &#xff08;3&#xff09;存储的信息…

未授权访问漏洞(非重点 中)

6.Hadoop 1.在 fofa 使用 port"8088" && app"Hadoop" 获取资源 2.打开后若无需登录,则存在漏洞 7.ActiveMQ 1.在 fofa 使用 body"ActiveMQ" && port"8161" 获取资源 2.打开后若点击登录,默认账户密码为 admin/adm…

【css】使用CSS绘制奥运五环--巴黎奥运

使用CSS绘制奥运五环 在2024年巴黎奥运会期间&#xff0c;本文来使用 CSS 来画一个奥运五环。奥运五环由五个相互交叠的圆环组成&#xff0c;分别代表五大洲。 奥运五环是相互连接的&#xff0c;因此在视觉上会产生重叠效果&#xff0c;这也是实现五环最有挑战性的部分 HTML结…

Rabbitmq的死信队列与如何利用死信队列实现延迟队列

如果设置了队列的 TTL 属性&#xff0c;那么一旦消息过期&#xff0c;就会被队列丢弃(如果配置了死信队列被丢到死信队列中)。而如果仅设置消息的 TTL 属性&#xff0c;即使消息过期&#xff0c;也不一定会被马上丢弃&#xff0c;因为消息是否过期是在即将投递到消费者之前判定…

HTML常用标签和CSS的运用

目录 1.HTML标签 1.1 文档结构标签 1.2 文本格式标签 1.3 列表标签 1.4 链接和媒体标签 1.5 表格标签 1.6 表单标签 1.7 分区和布局标签 1.8 元数据标签 2.css样式 2.1 字体样式 2.2 文本样式 2.3 背景样式 2.4 边框样式 2.5 间距样式 2.6 宽度和高度 2.7 显示…