八大排序算法——堆排序
目录
前言
一、向上调整算法建堆
二、向下调整算法建堆
三、堆排序
前言
堆排序是基于堆结构的一种排序思想,因此要为一个乱序的数组进行排序的前提是数组必须要是一个堆,所以要先对数组进行建堆操作
一、向上调整算法建堆
时间复杂度:O( n*logn )
由于向上调整算法建堆的时间复杂度的证明太过晦涩难懂,还要涉及数学中的错位相减法,所以这里就不证明了,感兴趣的可以自己去了解一下
这里只需要知道向上调整算法建堆的时间复杂度为 O( n*logn )
//交换两个数的位置
void sweap(int* num1, int* num2)
{int tmp = *num1;*num1 = *num2;*num2 = tmp;
}
//向上调整算法(大根堆)
void AdjustUp(int* arr, int pos)
{//当前调整的位置不能是堆顶if (pos == 0){return;}//寻找双亲节点int parents = (pos - 1) / 2;//当前位置与双亲节点进行比较//如果当前位置的数大于双亲节点,就进行交换,并且继续向上调整//如果当前位置的数小于双亲节点,表示堆已经构建好了if (arr[parents] < arr[pos]){//交换两个数位置sweap(&arr[parents], &arr[pos]);//继续向上调整AdjustUp(arr, parents);}
}
int main()
{//给定一个乱序数组int arr[] = { 8,3,2,6,7,1,4,9,5 };//计算数组元素个数int size = sizeof(arr) / sizeof(arr[0]);//向上调整算法建堆//从前往后依次调整建堆//先让节点之前的数为堆,然后整体为堆for (int i = 0; i < size; i++){AdjustUp(arr, i);}return 0;
}

二、向下调整算法建堆
时间复杂度:O( n )
由于向下调整算法建堆的时间复杂度的证明太过晦涩难懂,还要涉及数学中的错位相减法,所以这里就不证明了,感兴趣的可以自己去了解一下
这里只需要知道向下调整算法建堆的时间复杂度为 O( n )
//交换两个数的位置
void sweap(int* num1, int* num2)
{int tmp = *num1;*num1 = *num2;*num2 = tmp;
}
//向下调整算法(大根堆)
void AdjustDown(int* arr, int size, int pos)
{//左孩子位置int child = pos * 2 + 1;//向下调整算法,直到左孩子位置大于数组个数if (child < size){//选出左右孩子中最大的那个孩子if (child + 1 < size && arr[child] < arr[child + 1]){child++;}//与当前位置进行比较//如果左右孩子中最大数大于当前位置的数,就进行交换,并且继续向下调整//如果左右孩子中最大数小于当前位置的数,表示堆已经调整好了if (arr[child] > arr[pos]){//交换两个数的位置sweap(&arr[pos], &arr[child]);//继续向下调整AdjustDown(arr, size, child);}}
}
int main()
{//给定一个乱序数组int arr[] = { 8,3,2,6,7,1,4,9,5 };//计算数组元素个数int size = sizeof(arr) / sizeof(arr[0]);//向上调整算法建堆//从最后一个叶子节点父节点往前依次调整建堆//先让节点的左右子树为堆,然后整体为堆int pos = (size - 1) / 2;//最后一个叶子节点父节点for (int i = pos; i >= 0; i--){AdjustDown(arr, size, i);}return 0;
}

三、堆排序
时间复杂度:O( n*logn )
在进行建堆操作时我们可以选择向上调整算法和向下调整算法,但是由于向下调整算法的时间复杂度要优于向上调整算法,因此更推荐使用向下调整算法建堆
建堆的时间复杂度为O( n ),每次调整的堆结构的时间复杂度为O( logn ) ,因此整体时间复杂度为O( n*logn )
堆排序的过程大致如下:
- 将待排序的数组构造成一个大顶堆(或小顶堆,根据需要)。此时,整个数组的最大值(或最小值)就是堆结构的顶端
- 将顶端的数与末尾的数交换。此时,末尾的数为最大值(或最小值),剩余待排序数组个数为n-1
- 将剩余的n-1个数再构造成大顶堆(或小顶堆),再将顶端数与n-1位置的数交换。如此反复执行,便能得到有序数组
【注意】
- 排升序要建大堆
- 排降序要建小堆
整体代码实现
//交换两个数的位置
void sweap(int* num1, int* num2)
{int tmp = *num1;*num1 = *num2;*num2 = tmp;
}//向下调整算法(大根堆)
void AdjustDown(int* arr, int size, int pos)
{//左孩子位置int child = pos * 2 + 1;//向下调整算法,直到左孩子位置大于数组个数if (child < size){//选出左右孩子中最大的那个孩子if (child + 1 < size && arr[child] < arr[child + 1]){child++;}//与当前位置进行比较//如果左右孩子中最大数大于当前位置的数,就进行交换,并且继续向下调整//如果左右孩子中最大数小于当前位置的数,表示堆已经调整好了if (arr[child] > arr[pos]){//交换两个数的位置sweap(&arr[pos], &arr[child]);//继续向下调整AdjustDown(arr, size, child);}}
}//堆排序——升序
void HeapSort(int* arr, int size)
{//从后往前依次调整建堆//先让节点的左右子树为堆,然后整体为堆int pos = (size - 1) / 2;//最后一个叶子节点父节点for (int i = pos; i >= 0; i--){//向下调整建堆AdjustDown(arr, size, i);}//堆排序//排升序要建大堆//排降序要建小堆for (int i = 0; i < size; i++){//堆顶与最后一个有效元素交换位置sweap(&arr[0], &arr[size - 1 - i]);//向下调整,保持堆的结构AdjustDown(arr, size - i - 1, 0);}
}int main()
{//给定一个乱序数组int arr[] = { 8,3,2,6,7,1,4,9,5 };//计算数组元素个数int size = sizeof(arr) / sizeof(arr[0]);//堆排序HeapSort(arr, size);//打印排序后的数据for (int i = 0; i < size; i++){printf("%d ", arr[i]);}return 0;
}

相关文章:
八大排序算法——堆排序
目录 前言 一、向上调整算法建堆 二、向下调整算法建堆 三、堆排序 前言 堆排序是基于堆结构的一种排序思想,因此要为一个乱序的数组进行排序的前提是数组必须要是一个堆,所以要先对数组进行建堆操作 一、向上调整算法建堆 时间复杂度:O…...
U盘文件不翼而飞?这些数据恢复工具帮你找回!
U盘因其便携性是我们日常工作和生活中不可或缺的工具。不过有时候它也会出点小状况。如果你U盘里的数据突然不见了,不要着急,可以先试试这几款数据恢复工具! 福昕数据恢复 直达链接:www.pdf365.cn/foxit-restore/ 操作教程&…...
在Java中 try catch 会影响性能吗?
1、在Java中,异常处理确实会对性能产生影响,但在正常执行的代码路径中,即没有发生异常的情况下,try-catch块的性能影响是微不足道的 2、但是,如果出现异常被抛出时,Java虚拟机需要执行一些额外的操作来处理…...
吞吐量最高飙升20倍!破解强化学习训练部署难题
**强化学习(RL)对大模型复杂推理能力提升有关键作用,然而,RL 复杂的计算流程以及现有系统局限性,也给训练和部署带来了挑战。近日,字节跳动豆包大模型团队与香港大学联合提出 HybridFlow(开源项…...
redis的数据过期策略
Redis对数据设置了数据的有效时间,数据过期之后,就需要将数据从内存中删除掉.可以按照不同的规则进行删除,这种删除规则就被称之为数据的删除策略(数据过期策略),而这种策略有两种:惰性删除和定期删除 惰性删除:设置key过期时间后,我们不去管它,当需要该key时,我们在检查其是否…...
三周精通FastAPI:27 使用使用SQLModel操作SQL (关系型) 数据库
官网文档:https://fastapi.tiangolo.com/zh/tutorial/sql-databases/ SQL (关系型) 数据库 FastAPI不需要你使用SQL(关系型)数据库。 但是您可以使用任何您想要的关系型数据库。 这里我们将看到一个使用SQLModel的示例。 SQLModel是在SQLAlchemy和Pydantic的基础…...
Kubernetes金丝雀发布
华子目录 Canary金丝雀发布什么是金丝雀发布Canary发布方式基于header(http包头)灰度发布基于权重的金丝雀发布 Canary金丝雀发布 什么是金丝雀发布 金丝雀发布也称为灰度发布,是一种软件发布策略主要目的是在将新版本的软件全面推广到生产环…...
树形DP讲解
文章目录 树形DP讲解一、引言二、树形DP基础1、树的定义2、树形DP的基本思想3、代码示例:子树大小 三、经典例题解析1、树的平衡点1.1、代码示例 2、没有上司的舞会(树的最大独立集)2.1、代码示例 四、总结 树形DP讲解 一、引言 树形动态规…...
容器:如何调试容器
调试容器,主要是指的调试Dockerfile,调试Dockerfile中的各个命令的执行,大小等 1、docker history查看构建过程和所有的中间层 2、docker run rm -it -u root XXX sh,通过临时容器的方式启动,可以调试中间层文件 3、do…...
用图说明 CPU、MCU、MPU、SoC 的区别
CPU CPU 负责执行构成计算机程序的指令,执行这些指令所指定的算术、逻辑、控制和输入/输出(I/O)操作。 MCU (microcontroller unit) 不同的 MCU 架构如下,注意这里的 MPU 表示 memory protection unit MPU (microprocessor un…...
牛客周赛 Round 65
文章目录 超市思路:Solved: 雨幕思路:Solved: 闺蜜思路:Solved: 医生思路:Solved: 降温(easy)思路:Solved: F-降温(hard&a…...
超级经典的79个软件测试面试题(内含答案)
1、软件的生命周期(prdctrm) 计划阶段(planning)-〉需求分析(requirement)-〉设计阶段(design)-〉编码(coding)->测试(testing)->运行与维护(running maintrnacne) 测试用例 用例编号 测试项目 测试标题 重要级别 预置条件 输入数据 执行步骤 预期结果 2、问…...
【Mac】安装 F5-TTS
1、下载项目 项目地址:【GitHub】 SWivid F5-TTS 2、创建并激活 Python 虚拟环境 # 创建 Python 虚拟环境 userMac F5-TTS-main % python3 -m venv f5-tts# 激活进入 Python 虚拟环境 userMac F5-TTS-main % source f5-tts/bin/activate (f5-tts) userrMac F5-TT…...
Leaflet查询矢量瓦片偏移的问题
1、问题现象 使用Leaflet绘制工具查询出来的结果有偏移 2、问题排查 1)Leaflet中latLngToContainerPoint和latLngToLayerPoint的区别 2)使用Leaflet查询需要使用像素坐标 3)经排查发现,container获取的坐标是地图容器坐标&…...
存储引擎技术进化
B-tree 目前支撑着数据库产业的半壁江山。 50 年来不变而且人们还没有改变它的意向 鉴定一个算法的优劣,有一个学派叫 IO复杂度分析 ,简单推演真假便知。 下面就用此法分析下 B-tree(traditional b-tree) 的 IO 复杂度,对读、写 IO 一目了…...
CentOS 9 Stream 上安装 Maven
CentOS 9 Stream 上安装 Maven 在 CentOS 9 Stream 上安装 Maven,可以按照以下步骤进行: 更新系统软件包: sudo dnf update安装 Maven: CentOS 9 Stream 默认的包管理器中已经包含 Maven,你可以直接安装: s…...
强势改进!TCN-Transformer时间序列预测
强势改进!TCN-Transformer时间序列预测 目录 强势改进!TCN-Transformer时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现TCN-Transformer时间序列预测; 2.运行环境为Matlab2023b; 3.单个变量时间序…...
MyBatis的不同参数传递封装
MyBatis参数传递 传参方式 1. 使用 #{} 占位符 这是 MyBatis 中最常用的参数传递方式。它将参数直接替换到 SQL 语句中的占位符位置。 单个参数: <select id"selectUserById" resultType"User">SELECT * FROM users WHERE id #{id}…...
kotlin 协程方法总结
Kotlin 协程是一套强大的异步编程工具,以下是对 Kotlin 协程常用方法的总结: 1. 协程构建器 launch: 启动一个新的协程,不阻塞当前线程,返回一个 Job 对象。 GlobalScope.launch {// 协程体}async: 启动一个新的协程并返回一个…...
脉冲当量计算方法
脉冲的概念: 脉冲当量是指控制器输出一个定位控制脉冲时,所产生的定位控制移动的位移。在直线运动中,它表示移动的距离;在圆周运动中,它表示转动的角度。简而言之,脉冲当量就是电机接收一个脉冲信号后能够移…...
蓝桥杯JavaB组赛后复盘:从‘类斐波那契’到‘星际旅行’,我的解题思路与踩坑实录
蓝桥杯JavaB组赛后复盘:从‘类斐波那契’到‘星际旅行’,我的解题思路与踩坑实录 1. 考场策略与时间分配 比赛开始前15分钟,我快速浏览了所有题目,用铅笔在草稿纸上标注了每道题的预估难度和解题方向。这种策略让我避免了"死…...
实习生,企业的青春代言人
为什么优质的口碑是招募最好的助推器? 在校园招聘中,应届生们不仅看官网的宣传,更看重学长学姐的“真实评价”。一份优质的校招实习经历,不仅能为企业培养出未来的中坚力量,更能通过学生的自发传播,让实习…...
CTF新手必看:一张图里藏了啥?手把手教你用010 Editor秒解BUUCTF图片隐写题
CTF新手入门:从图片隐写题中快速提取Flag的实战指南 当你第一次接触CTF比赛中的图片隐写题时,可能会感到无从下手。那些看似普通的图片背后,往往藏着关键的Flag信息。本文将带你一步步破解BUUCTF平台上的典型图片隐写题,使用010 E…...
对比按需计费与套餐taotoken token plan在长期项目中的成本优势分析
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 对比按需计费与套餐:Taotoken Token Plan 在长期项目中的成本优势分析 1. 项目背景与成本考量 在长期依赖大模型 API …...
华为HCIA-Datacom认证 第七章第八章 案例教程
华为HCIA-Datacom认证 第七章&第八章 案例教程 一、背景延续:小明的网络运维新课题 前几次网络改造完成后,公司的办公网络已经稳定运行了一阵子。小明也从当初的手忙脚乱成长为一名能独立处理基础网络问题的工程师。然而,随着公司网络的不断扩展,新的管理需求随之而来…...
华硕笔记本性能优化神器:3步掌握G-Helper轻量级控制中心
华硕笔记本性能优化神器:3步掌握G-Helper轻量级控制中心 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, …...
app评论区升级成功
经过我10个小时的激情工作,评论区终于是可以运行起来了,而且我升级了系统,让代码更加直观和可维护。什么你说不好看,等会就好看了。...
[STM32U3] 【STM32U385RG 测评】PWM调节屏幕亮度
在评测计划中有使用pwm来实现调节屏幕亮度,因此本篇为如何使用HMI实现对屏的亮度调节。实现原理为,使用TouchGFX Designer添加一个滑动控件,通过滑动来修改pwm的占空比,实现ST7789的BLK的电压实现。 本次工程在上一篇试用的基础上…...
用STM32F103 DIY一个JTAG边界扫描测试仪(附完整源码与避坑记录)
用STM32F103 DIY一个JTAG边界扫描测试仪(附完整源码与避坑记录) 在嵌入式开发和硬件调试领域,验证PCB板或芯片的连通性一直是个令人头疼的问题。传统方法要么需要昂贵的专业设备,要么就得面对密密麻麻的测试点束手无策。而JTAG边界…...
给硬件工程师的芯片FT测试入门:从ATE、Handler到Socket,一次搞懂所有‘治具’
芯片FT测试全流程实战指南:从设备选型到治具配置 第一次走进芯片测试车间时,我被眼前那些闪烁着信号灯的庞大设备和精密治具震撼到了。作为硬件工程师,我们可能更熟悉PCB设计和电路仿真,但当芯片进入量产阶段,如何确保…...
