选择排序(直接选择排序与堆排序)----数据结构-排序②

1、选择排序

1.1 基本思想

        每一次从待排序的数据元素中选出最小(或最大)的一个元素,放在序列的起始位置,直到全部待排序的数据元素排完就停止 。

1.2 直接选择排序

排序思想:

①在元素集合array[i]--array[n-1]中选择数值最大(小)的数据元素。

②若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换,使最大(最小)的元素来到数据的最后(开始)。

③在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素。

动图演示:

 动图解释:

①遍历区间 [ 0, n-1 ] 的所有数,选出最小的数放到我们所遍历区间的最左端,第一次遍历区间最左端是0。

②遍历区间 [ 1, n-1 ] 的所有数,选出最小的数放到我们所遍历区间的最左端,第而二次遍历区间最左端是1。

③不断重复上述步骤,直至区间内的元素个数为一个时,停止遍历。

代码实现:

void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void SelectSort2(int* a, int n)
{int begin = 0, end = n - 1;// 区间为 [begin , end]while (begin < end)  // 当 begin == end 时,表明区间内还剩一个元素,停止遍历{// 假设最小值都为区间的最左端元素int mini = begin;for (int i = begin + 1; i <= end; i++){// 在区间内遇到更小的数就更新 miniif (a[i] < a[mini])mini = i;}// 第一次遍历结束,mini位置的值为该区间的最小值 Swap(&a[begin], &a[mini]);// 将最小值放到该区间的最左端// 缩小区间的长度begin++;}
}

代码优化:

        实际上在每一次的遍历中,我们不仅可以选出最小值放到区间的最左端,同时我们还可以选出最大值放到区间的最右端,这样可以减少我们的遍历次数。 

优化代码实现:

void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void SelectSort(int* a, int n)
{int begin = 0, end = n - 1;// 区间为 [begin , end]while(begin < end)  // 当 begin == end 时,表明区间内还剩一个元素,停止遍历{// 假设最大值与最小值都为区间最左端元素int maxi = begin, mini = begin;for (int i = begin + 1; i <= end; i++){// 在区间内遇到更大的数就更新 maxiif (a[i] > a[maxi])maxi = i;// 在区间内遇到更小的数就更新 miniif (a[i] < a[mini])mini = i;}// 第一次遍历结束,maxi、mini位置的值为该区间的最大值与最小值 Swap(&a[begin], &a[mini]);// 将最小值放到该区间的最左端// 当我们的区间最大值位于 begin 位置时,即maxi = begin时//因为我们上面的交换,导致begin位置的值已经被换到 mini 位置//所以现在最大值的下标是 miniif (maxi == begin)//当最大的数据在 begin 位置时,maxi = mini; Swap(&a[end], &a[maxi]); // 将最大值放到该区间的最右端// 缩小区间的长度begin++;end--;}
}

 直接选择排序的特性总结:

1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用

2. 时间复杂度:O(N^2)

3. 空间复杂度:O(1)

4. 稳定性:不稳定

不稳定的原因:当数组已经接近有序或已经完全有序时,每一次还是会进行找大找小,这样就会导致时间上的巨大浪费。

1.3 堆排序

       堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种,但相较于直接选择排序来说提升了许多 。它是通过堆(完全二叉树)来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。(如果还未学习堆的同学,可以移步到我的上一篇文章,里面有堆的详细介绍)

堆排序的排序思想:

如果我们想利用堆排升序:

①首先我们需要建立一个有N个数据的大堆;

②将堆顶的数据(最大)与最后一个数据(下标是N-1)交换,此时我们最大的数据就来到了最后(N-1的位置),这时我们就不用再需要去考虑最后一个元素了,因为最后一个元素已经是最大;

③再对前N-1个数据再次进行堆排序即可。

注意:此刻交换到堆顶的数据并不一定满足大堆的性质,所以还需要对堆顶的数据进行向下调整,使得满足大堆的性质。
 

示意图:


void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}void AdjustDown(HPDataType* a, int size,int parent)
{int child = 2 * parent + 1;while (child < size){if ((child + 1) < size && a[child + 1] > a[child])  // 找出左右孩子中较大一个{child++;}if (a[parent] < a[child])   // 如果孩子更大就交换,并且更新父节点与孩子节点{Swap(&a[parent], &a[child]);parent = child;child = 2 * parent + 1;} else     // 如果父节点更大表明不用再交换了 ,跳出循环{break;}}
}void HeapSort(int* a, int n)
{// 利用向下调整算法建立一个大堆for (int i = (n - 1-1) / 2; i >= 0; i--)  // n-1 是最后一个节点,(n-1-1)/2就是第一个非叶子节点{AdjustDown(a, n,i);}int end = n-1;  // end 表示最后一个元素的下标while(end>0)  //如果数据个数大于1个,才进行排序{Swap(&a[0], &a[end]);   // 堆顶与最后一个元素进行交换AdjustDown(a, end, 0); // 将堆顶的数据向下调整end--;           // 每排好一个就不用再考虑最后一个元素,相当与堆的数据减少一个}
}

堆排序的特性总结: 

1. 堆排序使用堆来选数,效率就高了很多

2. 时间复杂度:O(N*logN)

3. 空间复杂度:O(1)

4. 稳定性:不稳定

不稳定的原因与直接选择排序类似,当数组已经有序或接近有序时,还需要建堆从而导致已经有序或接近有序的数据又会被从新打乱进行排序,同样会造成时间上的浪费。

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

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

相关文章

C++三大特性之多态

1.多态 1.1多态的概念 在面向对象方法中一般是这样表述多态性的:向不同的对象发送同一个消息&#xff0c;不同的对象在接收时会产生不同的行为(即方法)也就是说&#xff0c;每个对象可以用自己的方式去响应共同的消息。所谓消息&#xff0c;就是调用函数&#xff0c;不同的行…

【JavaSE】面向对象---多态

前言 本篇以Java初学者视角写下&#xff0c;难免有不足&#xff0c;或者术语不严谨之处。如有错误&#xff0c;欢迎评论区指正。本篇说明多态相关的知识。若本文无法解决您的问题&#xff0c;可以去最下方的参考文献出&#xff0c;找出想要的答案。 多态概念 多态&#xff08…

【小白专用】C# Task 类异步操作-浅谈

注解 Task类表示不返回值并且通常以异步方式执行的单个操作。 Task 对象是在 .NET Framework 4 中首次引入的 基于任务的异步模式 的中心组件之一。 由于对象执行的工作 Task 通常在线程池线程上异步执行&#xff0c;而不是在主应用程序线程上同步执行&#xff0c;因此可以使用…

【上篇】从 YOLOv1 到 YOLOv8 的 YOLO 物体检测模型历史

YOLO 型号之所以闻名遐迩,主要有两个原因:其速度和准确性令人印象深刻,而且能够快速、可靠地检测图像中的物体。 在本文中,我将与大家分享我在阅读一篇长达 30 页的综合性论文时获得的见解,该论文深入探讨了 YOLO 模型的进步。 这篇评论全面概述了 YOLO 框架的演变过程,…

Python001

Python 是一种高级编程语言。它具有以下显著特点&#xff1a;1. 简单易学&#xff1a;语法相对简洁明了&#xff0c;对初学者很友好。2. 丰富的库&#xff1a;拥有大量强大的内置库和第三方库&#xff0c;可用于各种领域&#xff0c;如数据分析、机器学习、Web 开发等。3. 可读…

【无标题】 Notepad++ plugin JSONViewer 下载地址32位

JSONViewer download | SourceForge.net 1、下载插件压缩包并解压出dll&#xff1a;Jsonviewer2.dll&#xff08;64位&#xff09;或NPPJSONViewer.dll&#xff08;32位&#xff09;; 2.、拷贝对应dll到Notepad安装目录下的plugins目录。 3、重启Notepad程序&#xff0c;在插…

LeetCode刷题之HOT100之颜色分类

下午好呀&#xff0c;大家&#xff01;昨天估计是喝了假酒&#xff0c;现在没有胃口&#xff0c;喝酒真的没有任何好处。以后尽量避免此活动。今天几乎没睡觉&#xff0c;准备做完这题回宿舍&#xff0c;把电脑也带回去。 1、题目描述 2、逻辑分析 对颜色排序&#xff0c;要求…

读书笔记:左耳听风

程序员如何用技术变现 我完全没有必要通过打工听人安排而活着&#xff0c;而是反过来通过在公司工作提高自己的技能&#xff0c;让自己可以更为独立和自由地生活。 因而&#xff0c;在工作当中&#xff0c;对于那些没什么技术含量的工作&#xff0c;我基本上就像是在学生时代那…

NRF24L01(2.4G)模块的使用——SPI时序(软件)篇

一、SPI的简介&#xff1a; SPI 是英语Serial Peripheral interface的缩写&#xff0c;顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。 SPI&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且在芯片的管脚…

安装ps提示vcruntime140.dll丢失的解决方法,总结5种解决方法

在电脑使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“找不到vcruntime140.dll”。这个问题可能会导致程序无法正常启动或运行&#xff0c;因此了解其原因和解决方法是非常必要的。小编将从多个方面对“找不到vcruntime140.dll”这一问题进行详细…

iBeacon赋能AR导航:室内定位技术的原理与优势

室内定位导航对于大型商场、机场、医院等复杂室内环境至关重要&#xff0c;它帮助人们快速找到目的地&#xff0c;提高空间利用率。AR技术通过将虚拟信息叠加在现实世界&#xff0c;提供直观导航指引&#xff0c;正在成为室内导航的新趋势&#xff0c;增强用户互动体验&#xf…

【算法训练记录——Day27】

Day27——回溯算法Ⅲ 1.组合总和2.组合总和II3.分割回文串 内容 ● 39.组合总和 ● 40.组合总和II ● 131.分割回文串 1.组合总和 思路&#xff1a;和组合总和一样&#xff0c;先从candidates中遍历选择元素&#xff0c;但是纵向递归时所选择元素要包括当前元素 vector<int&…

玩游戏时服务器遭到DDOS攻击崩溃,DDOS攻击是什么?

某网游服务器突然崩溃&#xff0c;大量玩家被迫下线。随后该游戏官方出面解释是因服务器遭遇了DDoS攻击&#xff0c;所以导致登录异常。这个DDoS攻击到底是哪里来的鬼怪&#xff0c;敢这么给自己加戏&#xff1f; 什么是DDoS攻击&#xff1f; DDoS攻击&#xff0c;专业表述是“…

【启程Golang之旅】协程和管道操作

欢迎来到Golang的世界&#xff01;在当今快节奏的软件开发领域&#xff0c;选择一种高效、简洁的编程语言至关重要。而在这方面&#xff0c;Golang&#xff08;又称Go&#xff09;无疑是一个备受瞩目的选择。在本文中&#xff0c;带领您探索Golang的世界&#xff0c;一步步地了…

积累常用css

1、封面文字&#xff0c;垂直居中&#xff0c;可以两列并排 font-size: 20px;font-weight: 600;color: #333;line-height: 20px;display: block;word-wrap: break-word;writing-mode: vertical-lr;height: 160px;margin: 0 auto; 2、宽border效果 .dashed-box { margin: 80px…

ubuntu22.04编译OpenCV4.9(带contrib-4.9.0)

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;4.9.0 opencv_contrib版本&#xff1a;4.9.0 源码下载 OPenCV4.9.0下载地址&#xff1a;https://github.com/opencv/opencv/releases/tag/4.9.0 如下图所示&#xff1a; 按箭头所指点击下载source code(tar.gz)文件到…

从零开始实现自己的串口调试助手(9)-重置多文本框,保存/载入指令集

重置多文本框 添加多文本控件列表 在构造函数中把我们需要操作的控件归类到对应列表之中 //创建多文本存放数组 - 存放那三列内容 checkBox lineEdi btnfor(int i1;i<9;i){// 添加到按钮数组QString btnName QString("pushButton_t%1").arg(i); //构建对应控件名…

DSP问题:TMS320F280049延时和实际不符

1、问题现象 我之前写的一篇点灯文章&#xff0c;发现LED等闪烁频率和设想不一致&#xff0c;延时100ms&#xff0c;实际延时要更长。 2、问题原因 电路中使用的晶振是10MHz&#xff0c;实际代码中配置的是20MHz的晶振。 3、解决方案 修改代码中的晶振配置为10MHz即可。…

【Redis】Redis经典问题:缓存穿透、缓存击穿、缓存雪崩

目录 缓存的处理流程缓存穿透解释产生原因解决方案1.针对不存在的数据也进行缓存2.设置合适的缓存过期时间3. 对缓存访问进行限流和降级4. 接口层增加校验5. 布隆过滤器原理优点缺点关于扩容其他使用场景SpringBoot 整合 布隆过滤器 缓存击穿产生原因解决方案1.设置热点数据永不…