数据结构:选择排序

简单选择排序

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

算法步骤

  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.mzph.cn/news/42171.shtml

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

相关文章

【深度学习】PyTorch快速入门

【深度学习】学习PyTorch基础 介绍PyTorch 深度学习框架是一种软件工具&#xff0c;旨在简化和加速构建、训练和部署深度学习模型的过程。深度学习框架提供了一系列的函数、类和工具&#xff0c;用于定义、优化和执行各种深度神经网络模型。这些框架帮助研究人员和开发人员专注…

嵌入式Linux开发实操(九):CAN接口开发

前言: CAN网络在汽车中的使用可以说相当广泛。而CAN网络需要的收发器最常用的就是NXP 的TJA1042: CAN网络:

无涯教程-Perl - splice函数

描述 此函数从LENGTH元素的OFFSET元素中删除ARRAY元素,如果指定,则用LIST替换删除的元素。如果省略LENGTH,则从OFFSET开始删除所有内容。 语法 以下是此函数的简单语法- splice ARRAY, OFFSET, LENGTH, LISTsplice ARRAY, OFFSET, LENGTHsplice ARRAY, OFFSET返回值 该函数…

Vue 项目运行 npm install 时,卡在 sill idealTree buildDeps 没有反应

解决方法&#xff1a;切换到淘宝镜像。 以下是之前安装的 xmzs 包&#xff0c;用于控制切换淘宝镜像。 该截图是之前其他项目切换淘宝镜像的截图。 切换镜像后&#xff0c;顺利执行 npm install 。

生成国密密钥对

在线生成国密密钥对 生成的密钥对要妥善保管&#xff0c;丢失是无法找回的。

selinux

一、selinux的说明 二、selinux的工作原理 三、selinux的启动、关闭与查看 Enforcing和permissive都是临时的&#xff0c;重启还是依据配置文件中&#xff0c;禁用selinux&#xff0c;修改配置文件&#xff1a; 之后重启生效 四、selinux对linux服务的影响

【JAVA】我们该如何规避代码中可能出现的错误?(一)

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️初识JAVA】 文章目录 前言三种类型的异常异常处理JAVA内置异常类Exception 类的层次 前言 异常是程序中的一些错误&#xff0c;但并不是所有的错误都是异常&#xff0c;并且错误有时候是可以避免的&…

Grounding dino + segment anything + stable diffusion 实现图片编辑

目录 总体介绍总体流程 模块介绍目标检测&#xff1a; grounding dino目标分割&#xff1a;Segment Anything Model (SAM)整体思路模型结构&#xff1a;数据引擎 图片绘制 集成样例 其他问题附录 总体介绍 总体流程 本方案用到了三个步骤&#xff0c;按顺序依次为&#xff1a…

Tomcat 部署优化

Tomcat Tomcat 开放源代码web应用服务器&#xff0c;是由java代码开发的 tomcat就是处理动态请求和基于java代码的页面开发 可以在html当中写入java代码&#xff0c;tomcat可以解析html页面当中的iava&#xff0c;执行动态请求 动态页面机制有问题&#xff1a;不对tomcat进行优…

vue 使用indexDB 简单完整逻辑

1 npm npm install idb 2 代码 <template><div><p>Data: {{ data }}</p><button click"fetchData">Fetch Data</button></div> </template><script> import { openDB } from idb;export default {data() {…

eqtl-GWAS和GWAS-GWAS

目前教程中有eqtl-GWAS和GWAS-GWAS两种模式&#xff0c;其他模式比较少见&#xff0c;还未进行开发 数据类型cc为分类变量即case/control&#xff0c;quant为连续变量&#xff0c;eqtl数据默认quant coloc.abf有两个比较需要注意的点&#xff0c;就是数据集中N是代表样本量&am…

[Docker精进篇] Docker镜像构建和实践 (三)

前言&#xff1a; Docker镜像构建的作用是将应用程序及其依赖打包到一个可移植、自包含的镜像中&#xff0c;以便在不同环境中快速、可靠地部署和运行应用程序。 文章目录 Docker镜像构建1️⃣是什么&#xff1f;2️⃣为什么&#xff1f;3️⃣镜像构建一、用现有容器构建新镜像…

【IMX6ULL驱动开发学习】08.马达驱动实战:驱动编写、手动注册平台设备和设备树添加节点信息

目录 一、使用设备树 1.1 修改设备树流程 二、手动创建平台设备 三、总结&#xff08;附驱动程序&#xff09; 前情提要&#xff1a;​​​​​​​【IMX6ULL驱动开发学习】07.驱动程序分离的思想之平台总线设备驱动模型和设备树_阿龙还在写代码的博客-CSDN博客 手动注册…

Android中如何不编译源生模块

如果想让自己的app 替换系统的app 比如使用闪电浏览器替换系统的Browser 首先把闪电浏览器放到 vendor/rockchip/common/apps Android.mk LOCAL_PATH : $(call my-dir) include $(CLEAR_VARS)LOCAL_MODULE : Lightning LOCAL_SRC_FILES : $(LOCAL_MODULE).apk LOCAL_MODULE_C…

linux 命令- systemctl

systemctl 参数说明 1、使用语法 用法&#xff1a;systemctl [OPTIONS…] {COMMAND} … 2 、参数说明 参数参数说明start立刻启动后面接的unitstop立刻关闭后面接的unitrestart立刻关闭后启动后面接的unit&#xff0c;亦即执行stop再start的意思reload不关闭后面接的unit的…

常见程序搜索关键字转码

个别搜索类的网站因为用户恶意搜索出现误拦截情况&#xff0c;这类网站本身没有非法信息&#xff0c;只是因为把搜索关键字显示在网页中&#xff08;如下图&#xff09;&#xff0c;可以参考下面方法对输出的关键字进行转码 DEDECMS程序 本文针对Dedecms程序进行搜索转码&…

优先级队列【C++】

文章目录 priority_queuepriority_queue 使用priority_queue的模拟实现向上调整算法向下调整算法pushpoptopsizeempty 仿函数完整代码 priority_queue 优先队列&#xff08;priority_queue&#xff09;也是队列的一种&#xff0c;priority_queue的接口是和queue的接口是相同的…

C#__基本特性和使用

// 特性&#xff08;attribute&#xff09;: // 一种允许我们向程序集添加元数据的语言结构 // 用于保存程序结构信息的某种特殊类型的类 // 类似“批注”&#xff0c;用于解释说明 #define IsShowMessage // 宏定义&#xff0c;在开头定义&#xff0…

uni-app弹窗列表滚动, 弹框下面的内容也跟随滚动解决方案

滑动弹窗里的列表&#xff0c;弹框下面的内容也会跟着滑动&#xff0c;导致弹窗中的列表不能正常滚动 1.弹窗组件代码&#xff0c;需要在最外层的view中加入touchmove.stop.prevent"moveHandle"&#xff0c;且弹窗中需要滚动的列表要使用scroll-view标签包裹起来&…

五分钟搭建生鲜蔬果小程序

如今&#xff0c;随着移动互联网的快速发展&#xff0c;小程序已经成为众多企业和商家推广产品和服务的重要工具。而生鲜蔬果行业作为一个常见的消费领域&#xff0c;也开始逐渐转向小程序商城来进行销售和服务。那么&#xff0c;如何从零开始搭建一个生鲜蔬果小程序商城呢&…