DS八大排序之直接选择排序和堆排序

前言

上一期我们已经介绍了,排序、为什么要有排序以及排序在实际生活中的应用。并且介绍并实现了直接插入排序和它的优化即希尔排序~!本期我们再来学习一组排序 ---- "选择排序"即直接选择排序和堆排序~!

本期内容介绍

直接选择排序

堆排序

选择排序的基本思想

每次从待排序的数据元素的序列中选出最小或最大的一个元素存放在当前序列的起始位置,直到将全部待排序的数据元素排完。

直接选择排序

在元素集合a[i].....a[n-1]中,选择一个最大最小的数据,如果他不是这个序列中的最后一个第一个,则该序列中的最后一个第一个进行交换,将剩余的元素重复上述操作,直到序列的元素只有一个则结束!

OK,举个栗子画个图(这里是以升序距离的):

OK,直接选择排序的过程就是这样的,下面我们来实现一下:还是和以前一样,先写单趟再来改造整体:

单趟

int left = begin;//当前序列的最左端
int min = begin;//最小的元素的下标
for (int i = begin; i < n; i++)
{if (a[min] > a[i])min = i;
}Swap(&a[left], &a[min]);//最左端的元素与当前序列中最小的元素交换

整体

直接选择排序改造整体也很简单,只需要,让每个元素都重复单趟即可~!

void SelectSort(int* a, int n)
{for (int begin = 0; begin < n; begin++){int left = begin;//当前序列的最左端int min = begin;//最小的元素的下标for (int i = begin; i < n; i++){if (a[min] > a[i])min = i;}Swap(&a[left], &a[min]);//最左端的元素与当前序列中最小的元素交换}
}

OK,测试一下:

OK,没有问题。这样写实每次找到当前序列中最小的一个,然后与最左端(升序)交换,我们其实可以对他进行一个小优化的--->每次找到当前序列中的两个元素(一个最小,一个最大),最小的与当前序列的最左端交换,最大与当前序列的最右端交换~!

OK,还是先写单趟,在改造多趟:

单趟

int min = begin, max = begin;
for (int i = begin + 1; i <= right; i++)
{if (a[min] > a[i])min = i;//选出最小if (a[max] < a[i])max = i;//选出最大
}Swap(&a[begin], &a[min]);//最小与左端交换
Swap(&a[right], &a[max]);//最大与右端交换

整体

void SelectSort(int* a, int n)
{int begin = 0, right = n - 1;while (begin < right){int min = begin, max = begin;for (int i = begin + 1; i <= right; i++){if (a[min] > a[i])min = i;if (a[max] < a[i])max = i;}Swap(&a[begin], &a[min]);Swap(&a[right], &a[max]);++begin;--right;}
}

这就是一次选出两个的整体。OK,我们来个栗子测试一下:

怎么没有实现排序呢?是我们的思想有问题???OK,遇事不慌,调试走起:

这是调试找到的第一次最大和最小的元素的下标~!然后下来就是最小与左端交换,最大与右端交换,但此时最大恰好在最左端,一执行最小与最左端交换后在在执行在最大与最右交换时发现最大的已经不在原来的位置了~!这就导致了上述的乱序!

解决方案:在交换完最小与最左端后,判断一下最大的位置,如果最大的是在最左端,则此时最大值应该被换到了最小值的位置,因此,我们只需要调整一下最大值是在最小值的位置即可,即max = min~!

void SelectSort(int* a, int n)
{int left = 0, right = n - 1;while (left < right){int min = left, max = left;for (int i = left + 1; i <= right; i++){if (a[min] > a[i])min = i;if (a[max] < a[i])max = i;}Swap(&a[left], &a[min]);if (max == left)max = min;Swap(&a[right], &a[max]);++left;--right;}
}

再来测试一下:

OK,没有问题了~!

复杂度分析

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

单趟无论选择一个还是选择两个,都得遍历一遍,复杂度为O(N),整体还得遍历一遍O(N)

空间复杂度:O(1)

堆排序

堆排序其实在前面的二叉树堆那里已经介绍并实现过了,这来就等于回顾式的再过一遍~!如果想了解堆这种他是具体咋搞的请点击:二叉树的实现

堆排序(Heapsort)是指利用堆,这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据进行实现排序的。

他既然是借助堆来实现的那得有堆,即要建堆。这里有两种建堆的方式:向上调整建堆+向下调整排序,向下调整建堆+向下调整排序!

他排序是采用删除的思想把最大或最小的换到最后,然后对前N-i(i=1,2,3...n)个进行向下调整!
注意:升序建大堆,降序建小堆

OK,举个排序的例子:

向上调整建堆

void HeapSort(HPDataType* a, int n)
{//向上调整建堆//O(N*lgN)for (int i = 1; i < n; i++){AdjustUp(a, i);}//向下调整排序//O(N*lgN)int end = n - 1;while (end){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}

这里的向上调整建堆和上面堆的插入是一个思路!时间复杂度是O(lgN*N),向下调整排序的时间复杂度是:O(N*lgN)---->有n个元素,每排好一个一下下标,也就是上面的删除的思路!

向下调整建堆

void HeapSort(HPDataType* a, int n)
{//向下调整建堆//O(N)for (int i = (n - 1) / 2; i >= 0; i--){AdjustDown(a, n, i);}//向下调整排序//O(N*lgN)int end = n - 1;while (end){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}

向下调整建堆,就是从倒数第一个元素的父节点开始向下调整为堆!这样越往上层节点的左右子树必定是堆!

OK,测试一下:

没问题~!

复杂度分析

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

向下调整和向上调整的时间复杂度都是O(logN)即最多调整高度次,但向上调整建堆是O(N*log)而向下调整建堆的O(N)如下图~!删除排序的时间复杂度是O(N*logN),所以综合下来就是O(N*logN)

空间复杂度:O(1)

向下调整建堆时间复杂度推导

向上调整建堆时间复杂度推导

OK,本期分享就到这里,好兄弟,下期交换排序不见不散~!

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

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

相关文章

【机器视觉技术栈】- 机器视觉基础

1.1 为什么采用机器视觉 人眼与机器视觉对比 人眼机器视觉精确性差&#xff0c;64灰度级&#xff0c;不能分辨小于100微米的目标强&#xff0c;256灰度级&#xff0c;可检测微米级目标速度慢&#xff0c;无法看清间隔小于40毫秒的运动目标快&#xff0c;快门时间可达10微秒适…

操作系统背景知识

一、程序分类 程序按其运行环境分为&#xff1a; 裸机程序&#xff1a;直接运行在对应硬件上的程序 应用程序&#xff1a;只能运行在对应操作系统上的程序 二、计算机系统的层次结构 计算机系统两种层次结构&#xff1a; 2.1 无操作系统的简单的两层结构 2.2 有操作系统的…

企业软件的分类有哪些|app小程序定制开发

企业软件的分类有哪些|app小程序定制开发 企业软件是指为了满足企业运营和管理需求而开发的软件系统。根据不同的功能和应用领域&#xff0c;企业软件可以分为以下几个分类&#xff1a; 1. 企业资源计划&#xff08;Enterprise Resource Planning&#xff0c;ERP&#xff09;软…

云计算生成式 -给你不一样的音乐推荐新体验

目录 摘要&#xff1a; 正文&#xff1a; 一、亚马逊云与生成式 AI 结合的展望/总结 二、我用亚马逊云科技生成式 AI 产品打造了什么&#xff0c;解决了什么问题 三、未来云端技术发展趋势的见解 四、云端技术未来需要解决的问题 1、如何保护数据安全和隐私&#xff1f; …

一个菜单两个二级路由的搭建

效果如下&#xff0c;而且这是最上方的菜单&#xff0c;需要进入以后重定向。 {path: /,name: HOME,component: ConsoleLayout, //这里也有router-viewmeta: {menu: false},redirect: {name: ManagerList},children: [{path: /rightsManage,name: RightsManage,component: () &…

【FMC140】 基于VITA57.4标准的双通道5.2GSPS(或单通道10.4GSPS)射频采样FMC+子卡模块

板卡概述 FMC140是一款具有缓冲模拟输入的低功耗、12位、双通道&#xff08;5.2GSPS/通道&#xff09;、单通道10.4GSPS、射频采样ADC模块&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.1规范&#xff0c;该模块可以作为一个理想的IO单元耦合至FPGA前端&#xff0c;8通道…

第三届大湾区跨境物流商交会 深航协华南会14周年庆盛大召开

2023年11月28日&#xff0c;华南物流商会年度盛典:第三届大湾区跨境物流商交会 暨 深航协华南会十四周年庆在深圳市龙华希尔顿逸林酒店隆重举行。长沙市驻深办事处刘永红主任、深圳市商务局鲁云帆处长、深圳市航空业协会朱庆峰会长、深圳市物流行业协会王利强会长、深圳市跨境电…

11.30固定成本,完全竞争市场,无差异曲线,帕累托最优

固定成本 固定成本是指不随生产量变化而变化的成本&#xff0c;它是企业在生产过程中无论产量高低都必须支付的成本。计算固定成本的方法如下&#xff1a; 确定固定成本的项目&#xff1a;首先需要确定固定成本的项目&#xff0c;例如租金、折旧费、固定人工费用等。 收集相关…

暗物质:揭秘宇宙的隐形奥秘

暗物质:揭秘宇宙的隐形奥秘 一、引言 在浩瀚的宇宙中,有一种神秘的存在,它虽然看不见、摸不着,但却对宇宙的结构和演化起着至关重要的作用。这种存在就是暗物质。暗物质的研究是天文学和物理学领域的热点之一,科学家们正在利用各种手段来揭示它的奥秘。在本文中,我们将一…

学习k8s的介绍(一)

一、kubernetes及Docker相关介绍 1、kubernetes是什么 1-1、简称为k8s或kube&#xff0c;是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;可促进声明式配置和自动化。 声明式配置语法&#xff1a; kubectl create/apply/delete -f xx…

11-30 SpringBoot2

热部署 开发过程中,修改代码,不需要重启,自动更新 项目上线,一定要关闭 SpringBoot热部署的实现&#xff1f;&#xff1f; ideal默认阻止class类更新 2&#xff0e;需要手动构建项目&#xff0c;可以使用快捷键激活此功能ctrl F9 / build project 自动构建项目 允许程序运行…

链表高频面试题

1. 两个链表第一个公共子节点 LeetCode160 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; listA [4,1,8,4,5], listB [5…

CompletableFuture使用

一、核心API public static CompletableFuture<Void> runAsync(Runnable runnable)public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor)public static <U> CompletableFuture<U> supplyAsync(Supplier<U> su…

【智能家居】二、添加火灾检测模块(烟雾报警功能点)

可燃气体传感器 MQ-2 和 蜂鸣器 代码段 controlDevice.h&#xff08;设备控制&#xff09;smokeAlarm.c&#xff08;烟雾报警器&#xff09;buzzer.c&#xff08;蜂鸣器&#xff09;mainPro.c&#xff08;主函数&#xff09;运行结果 可燃气体传感器 MQ-2 和 蜂鸣器 代码段 …

Pycharm配置jupyter使用notebook详细指南(可换行conda环节)

本教程为事后记录&#xff0c;部分图片非实操图片。 详细记录了pycharm配置jupyter的方法&#xff0c;jupyter添加其他conda环境的方法&#xff0c;远程密码调用jupyter的方法&#xff0c;修改jupyter工作目录的方法。 文章目录 一、入门级配置1. Pycharm配置Conda自带的jupyt…

华为云cce负载配置时间同步

华为云cce将负载配置好之后&#xff0c;发现里面的时间与真实时间不同步&#xff0c;差了12小时&#xff0c;怎么办&#xff1f; 这时候就需要配置时间同步了。 华为云cce里面通过配置数据存储的路径来解决这个问题的&#xff0c;配置后&#xff0c;需要重启负载。 新建负载…

三、shell - 变量

目录 1、简介 1.1 变量的定义语法: 1.2 变量的定义需遵循的规则 1.3 变量的作用域 2、用户变量 2.1 定义变量 2.2 访问变量 2.3 变量的其他赋值方式 2.4 只读变量 2.5 删除变量 ​​​​​​​3、环境变量 ​​​​​​​3.1 常见的环境变量 ​​​​​​​3.2 自…

030 - STM32学习笔记 - ADC(四) 独立模式多通道DMA采集

030 - STM32学习笔记 - ADC&#xff08;四&#xff09; 独立模式多通道DMA采集 中断模式和DMA模式进行单通道模拟量采集&#xff0c;这节继续学习独立模式多通道DMA采集&#xff0c;使用到的引脚有之前使用的PC3&#xff08;电位器&#xff09;&#xff0c;PA4&#xff08;光敏…

【刷题笔记】串联所有单词的子串||暴力通过||滑动窗口

串联所有单词的子串 1 题目描述 https://leetcode.cn/problems/substring-with-concatenation-of-all-words/ 给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 …

基于STC12C5A60S2系列1T 8051单片机的液晶显示器LCD1602显示整数、小数应用

基于STC12C5A60S2系列1T 8051单片机的液晶显示器LCD1602显示整数、小数应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍液晶显示器LCD1602简单介绍IIC通信简单介绍…