数据结构:选择排序

简单选择排序

选择排序是一种简单直观的排序算法。首先在未排序序列中找到最大(最小)的元素,存放到排序学列的其实位置,然后在剩余的未排序的元素中寻找最小(最大)元素,存放在已排序序列的后面

算法步骤

  1. 在未排序序列中找到最大(小)元素,存放在排序序列的起始位置
  2. 再从剩余的未排序序列中找到最大(小)元素,然后存放在已排序序列的后面
  3. 重复上诉第二步骤,直至排序结束

算法理解

例如对无序表{56,12,80,91,20}采用简单选择排序算法进行排序,具体过程为:

  • 第一次遍历时,从下标为 1 的位置即 56 开始,找出关键字值最小的记录 12,同下标为 0 的关键字 56 交换位置:

    在这里插入图片描述

  • 第二次遍历时,从下标为 2 的位置即 56 开始,找出最小值 20,同下标为 2 的关键字 56 互换位置:

    在这里插入图片描述

  • 第三次遍历时,从下标为 3 的位置即 80 开始,找出最小值 56,同下标为 3 的关键字 80 互换位置:

    在这里插入图片描述

  • 第四次遍历时,从下标为 4 的位置即 91 开始,找出最小是 80,同下标为 4 的关键字 91 互换位置:

    在这里插入图片描述

  • 到此简单选择排序算法完成,无序表变为有序表。

代码实现

#include "iostream"
using namespace std;#define MAX 9
//单个记录的结构体
typedef struct {int key;
}SqNote;
//记录表的结构体
typedef struct {SqNote r[MAX];int length;
}SqList;
//交换两个记录的位置
void swap(SqNote *a,SqNote *b){int key=a->key;a->key=b->key;b->key=key;
}
//查找表中关键字的最小值
int SelectMinKey(SqList *L,int i){int min=i;//从下标为 i+1 开始,一直遍历至最后一个关键字,找到最小值所在的位置while (i+1<L->length) {if (L->r[min].key>L->r[i+1].key) {min=i+1;}i++;}return min;
}
//简单选择排序算法实现函数
void SelectSort(SqList * L){for (int i=0; i<L->length; i++) {//查找第 i 的位置所要放置的最小值的位置int j=SelectMinKey(L,i);//如果 j 和 i 不相等,说明最小值不在下标为 i 的位置,需要交换if (i!=j) {swap(&(L->r[i]),&(L->r[j]));}}
}
int main() {SqList *L = new SqList;L->length=8;L->r[0].key=49;L->r[1].key=38;L->r[2].key=65;L->r[3].key=97;L->r[4].key=76;L->r[5].key=13;L->r[6].key=27;L->r[7].key=49;SelectSort(L);for (int i=0; i<L->length; i++) {cout << L->r[i].key << " ";}return 0;
}

代码实现

13 27 38 49 49 65 76 97

树形选择排序

树形选择排序(又称“锦标赛排序”),是一种按照锦标赛的思想进行选择排序的方法,即所有记录采取两两分组,筛选出较小(较大)的值;然后从筛选出的较小(较大)值中再两两分组选出更小(更大)值,依次类推,直到最后选出一个最小(最大)值。同样可以采用此方式筛选出次小(次大)值等

算法理解

整个排序的过程,可以用一棵具有 n 个叶子结点的完全二叉树表示。例如对无序表{49,38,65,97,76,13,27,49}采用树形选择的方式排序,过程如下:

  • 首先将无序表中的记录采用两两分组,筛选出各组中的较小值(如图 1 中的(a)过程);然后将筛选出的较小值两两分组,筛选出更小的值,以此类推(如图 1 中的(b)(c)过程),最终整棵树的根结点中的关键字即为最小关键字:

在这里插入图片描述

图 1 树形选择排序(一)

  • 筛选出关键字 13 之后,继续重复此方式找到剩余记录中的最小值,此时由于关键字 13 已经筛选完成,需要将关键字 13 改为“最大值”,继续重复此过程,如图 2 所示: 图 2 树形选择排序(二)

    在这里插入图片描述

通过不断地重复此过程,可依次筛选出从小到大的所有关键字。该算法的时间复杂度为O(nlogn),同简单选择排序相比,该算法减少了不同记录之间的比较次数,但是程序运行所需要的空间较多。

代码实现

#include "iostream"
using namespace std;
#define N 8
void TreeSelectionSort(int *mData)
{int MinValue = 0;int tree[N * 4]; // 树的大小int max, maxIndex, treeSize;int i, n = N, baseSize = 1;while (baseSize < n)baseSize *= 2;treeSize = baseSize * 2 - 1;for (i = 0; i < n; i++) {//将要排的数字填到树上tree[treeSize - i] = mData[i];}for (; i < baseSize; i++) {//其余的地方都填上最小值tree[treeSize - i] = MinValue;}// 构造一棵树,大的值向上构造for (i = treeSize; i > 1; i -= 2){tree[i / 2] = (tree[i] > tree[i - 1] ? tree[i] : tree[i - 1]);}n -= 1;while (n != -1){max = tree[1];        //树顶为最大值mData[n--] = max;     //从大到小倒着贴到原数组上maxIndex = treeSize;  //最大值下标while (tree[maxIndex] != max) {maxIndex--;}//找最大值下标tree[maxIndex] = MinValue;while (maxIndex > 1) {if (maxIndex % 2 == 0) {tree[maxIndex / 2] = (tree[maxIndex] > tree[maxIndex + 1] ? tree[maxIndex] : tree[maxIndex + 1]);}else {tree[maxIndex / 2] = (tree[maxIndex] > tree[maxIndex - 1] ? tree[maxIndex] : tree[maxIndex - 1]);}maxIndex /= 2;}}
}
int main()
{int a[N] = {49,38,65,97,76,13,27,49};TreeSelectionSort(a);for (int i = 0; i < N; i++) {cout << a[i] << " ";}return 0;
}

运行结果

13 27 38 49 49 65 76 97

堆排序

堆排序 ( H e a p s o r t ) (Heapsort) (Heapsort)是指利用堆来实现的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。堆排序可以说是一种利用堆的概念来排序的选择排序。堆排序的平均时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)。分为两种方法:

  1. 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
  2. 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;

在这里插入图片描述

算法思想

了解了堆的基本性质之后,我们就可以看堆排序的基本思想。

  1. 将未排序的序列构造成大(或者小)顶堆,根据堆的性质我们可以找到序列中的最大(或者最小)值
  2. 把堆首和堆尾互换,并把堆的大小减 1 1 1
  3. 重复上面的步骤,直到堆的大小为 1 1 1

在这里插入图片描述

在这里插入图片描述

代码实现

#include "iostream"
using namespace std;
#define MAX 9
//单个记录的结构体
typedef struct {int key;
}SqNote;
//记录表的结构体
typedef struct {SqNote r[MAX];int length;
}SqList;
//将以 r[s]为根结点的子树构成堆,堆中每个根结点的值都比其孩子结点的值大
void HeapAdjust(SqList * H,int s,int m){SqNote rc=H->r[s];//先对操作位置上的结点数据进行保存,放置后序移动元素丢失。//对于第 s 个结点,筛选一直到叶子结点结束for (int j=2*s; j<=m; j*=2) {//找到值最大的孩子结点if (j+1<m && (H->r[j].key<H->r[j+1].key)) {j++;}//如果当前结点比最大的孩子结点的值还大,则不需要对此结点进行筛选,直接略过if (!(rc.key<H->r[j].key)) {break;}//如果当前结点的值比孩子结点中最大的值小,则将最大的值移至该结点,由于 rc 记录着该结点的值,所以该结点的值不会丢失H->r[s]=H->r[j];s=j;//s相当于指针的作用,指向其孩子结点,继续进行筛选}H->r[s]=rc;//最终需将rc的值添加到正确的位置
}
//交换两个记录的位置
void swap(SqNote *a,SqNote *b){int key=a->key;a->key=b->key;b->key=key;
}
void HeapSort(SqList *H){//构建堆的过程for (int i=H->length/2; i>0; i--) {//对于有孩子结点的根结点进行筛选HeapAdjust(H, i, H->length);}//通过不断地筛选出最大值,同时不断地进行筛选剩余元素for (int i=H->length; i>1; i--) {//交换过程,即为将选出的最大值进行保存大表的最后,同时用最后位置上的元素进行替换,为下一次筛选做准备swap(&(H->r[1]), &(H->r[i]));//进行筛选次最大值的工作HeapAdjust(H, 1, i-1);}
}int main() {SqList *L = new SqList ;L->length=8;L->r[1].key=49;L->r[2].key=38;L->r[3].key=65;L->r[4].key=97;L->r[5].key=76;L->r[6].key=13;L->r[7].key=27;L->r[8].key=49;HeapSort(L);for (int i=1; i<=L->length; i++) {cout << L->r[i].key << " ";}return 0;
}

运行结果

13 27 38 49 49 65 76 97

注意:堆排序相对于树形选择排序,其只需要一个用于记录交换(rc)的辅助存储空间,比树形选择排序的运行空间更小。

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

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

相关文章

cmake扩展(1)——VS+CMake创建Qt项目

创建项目 创建CMakeLists #cmake最低版本 cmake_minimum_required(VERSION 3.10) #项目名 project(regextool)#查找所有*.h,*.ui,*.cpp文件&#xff0c;并存入SOURCES中 file(GLOB SOURCES "*.cpp" "*.ui" "*.h")#开启moc set(CMAKE_AUTOMOC O…

计算机视觉中的特征检测和描述

一、说明 这篇文章是关于计算机视觉中特征检测和描述概念的简要理解。在其中&#xff0c;我们探讨了它们的定义、常用技术、简单的 python 实现和一些限制。 二、什么是特征检测和描述&#xff1f; 特征检测和描述是计算机视觉中的基本概念&#xff0c;在图像识别、对象跟踪和图…

Opencv特征检测之ORB算法原理及应用详解

Opencv特征检测之ORB算法原理及应用详解 特征是图像信息的另一种数字表达形式。一组好的特征对于在指定 任务上的最终表现至关重要。视觉里程 &#xff08;VO&#xff09; 的主要问题是如何根据图像特征来估计相机运动。但是&#xff0c;整幅图像用来计算分析通常比较耗时&…

机器学习终极指南:特征工程(02/2) — 第 -2 部分

接上文&#xff1a;机器学习终极指南&#xff1a;特征工程&#xff08;01/2&#xff09; 五、处理不平衡数据 处理不平衡的数据是机器学习的一个重要方面。不平衡数据是指目标变量的分布不均匀&#xff0c;并且与另一个类相比&#xff0c;一个类的代表性不足。这可能导致模型…

[内网渗透]CFS三层靶机渗透

文章目录 [内网渗透]CFS三层靶机渗透网络拓扑图靶机搭建Target10x01.nmap主机探活0x02.端口扫描0x03.ThinkPHP5 RCE漏洞拿shell0x04.上传msf后门(reverse_tcp)反向连接拿主机权限 内网渗透Target2&#xff08;1&#xff09;路由信息探测&#xff08;2&#xff09;msf代理配置&a…

两个数组的交集-C语言/Java

描述 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序。&#xff08;1 < nums1.length, nums2.length < 1000&#xff0c;0 < nums1[i], nums2[i] < 1000&#xff09; 示例1 输入…

yolov5代码解读之train.py【训练模型】

哇咔咔&#xff0c;登场 代码开头都是一些导包到模块的&#xff1a; 接下来来到入口函数&#xff1a; 我们直接来到main函数的内容&#xff1a;&#xff08;分四个部分&#xff09; 前两部分&#xff1a; 关于main函数的第二部分中的resume参数&#xff08;496行&#xff09;&…

概率图模型(Probabilistic Graphical Model,PGM)

概率图模型&#xff08;Probabilistic Graphical Model&#xff0c;PGM&#xff09;&#xff0c;是一种用图结构来描述多元随机变量之间条件独立性的概率模型。它可以用来表示复杂的概率分布&#xff0c;进行有效的推理和学习&#xff0c;以及解决各种实际问题&#xff0c;如图…

mysql延时问题排查

背景介绍 最近遇到一个奇怪的问题&#xff0c;有个业务&#xff0c;每天早上七点半产生主从延时&#xff0c;延时时间12.6K&#xff1b; 期间没有抽数/备份等任务&#xff1b;查看慢日志发现&#xff0c;期间有一个delete任务&#xff0c;在主库执行了161s delete from xxxx_…

人类:我觉得1+1=956446,你觉得呢?大模型:啊对对对

大模型太「听话」了怎么办&#xff1f; 大型语言模型&#xff08;LLM&#xff09;的自然语言理解与生成能力一直备受称赞&#xff0c;特别是 ChatGPT 等对话式语言模型能够与人类流畅、自然地进行多轮对话。然而&#xff0c;最近一篇 Google DeepMind 的论文研究发现 LLM 普遍存…

企业权限管理(八)-登陆使用数据库认证

Spring Security 使用数据库认证 在 Spring Security 中如果想要使用数据进行认证操作&#xff0c;有很多种操作方式&#xff0c;这里我们介绍使用 UserDetails 、 UserDetailsService来完成操作。 UserDetails public interface UserDetails extends Serializable { Collecti…

转义字符\

转移字符&#xff0c;就是通过字符&#xff0c;来转变原来字符的意思 常见的转义字符&#xff1a; 1、 2 注&#xff1a;" 的作用和他是类似的 3 4、 当打印\a时&#xff0c;电脑会出现一个警告&#xff0c;蜂鸣的声音 5、 阿斯克码表

机器学习---对数几率回归

1. 逻辑回归 逻辑回归&#xff08;Logistic Regression&#xff09;的模型是一个非线性模型&#xff0c; sigmoid函数&#xff0c;又称逻辑回归函数。但是它本质上又是一个线性回归模型&#xff0c;因为除去sigmoid映射函 数关系&#xff0c;其他的步骤&#xff0c;算法都是…

行业追踪,2023-08-09

自动复盘 2023-08-09 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

Apache RocketMQ 命令注入

漏洞简介 RocketMQ 5.1.0及以下版本&#xff0c;在一定条件下&#xff0c;存在远程命令执行风险。RocketMQ的NameServer、Broker、Controller等多个组件外网泄露&#xff0c;缺乏权限验证&#xff0c;攻击者可以利用该漏洞利用更新配置功能以RocketMQ运行的系统用户身份执行命…

Java代理模式——静态代理与动态代理

代理模式 代理模式允许你为其他对象提供一个代理&#xff0c;以控制对这个对象的访问。代理模式在不改变实际对象的情况下&#xff0c;可以在访问对象时添加额外的功能。 可以理解为代理模式为被代理对象创造了一个替身&#xff0c;调用者可以通过这个替身去实现这个被代理对…

网络安全 Day30-容器架构上

容器架构上 1. 容器架构1.1 什么是容器1.2 容器 vs 虚拟机(化) :star::star:1.3 Docker极速上手指南1&#xff09;使用rpm包安装docker2) docker下载镜像加速的配置3) 载入镜像大礼包&#xff08;老师资料包中有&#xff09; 1.4 Docker使用案例1&#xff09; 案例01&#xff1…

【算法篇C++实现】常见查找算法

文章目录 &#x1f680;一、预备知识⛳&#xff08;一&#xff09;查找的定义⛳&#xff08;二&#xff09;数组和索引 &#x1f680;二、二分查找&#x1f680;三、穷举搜索&#x1f680;四、并行搜索⛳&#xff08;一&#xff09;并发的基本概念⛳&#xff08;二&#xff09;…

行业追踪,2023-08-10

自动复盘 2023-08-10 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

关于MPU6050的VLOGIC引脚作用

关键字&#xff1a;MPU6X0X、 MPU6050、数字逻辑电平、VLOGIC 框图&#xff1a; 一、VLOGIC引脚作用? VLOGIC引脚主要用于设置为I2C供电引脚&#xff0c;以保证正确的I2C通信。 The bias and LDO section generates the internal supply and the reference voltages and cu…