八大排序算法——堆排序
目录
前言
一、向上调整算法建堆
二、向下调整算法建堆
三、堆排序
前言
堆排序是基于堆结构的一种排序思想,因此要为一个乱序的数组进行排序的前提是数组必须要是一个堆,所以要先对数组进行建堆操作
一、向上调整算法建堆
时间复杂度: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: 启动一个新的协程并返回一个…...
脉冲当量计算方法
脉冲的概念: 脉冲当量是指控制器输出一个定位控制脉冲时,所产生的定位控制移动的位移。在直线运动中,它表示移动的距离;在圆周运动中,它表示转动的角度。简而言之,脉冲当量就是电机接收一个脉冲信号后能够移…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...
Netty自定义协议解析
目录 自定义协议设计 实现消息解码器 实现消息编码器 自定义消息对象 配置ChannelPipeline Netty提供了强大的编解码器抽象基类,这些基类能够帮助开发者快速实现自定义协议的解析。 自定义协议设计 在实现自定义协议解析之前,需要明确协议的具体格式。例如,一个简单的…...
Spring事务传播机制有哪些?
导语: Spring事务传播机制是后端面试中的必考知识点,特别容易出现在“项目细节挖掘”阶段。面试官通过它来判断你是否真正理解事务控制的本质与异常传播机制。本文将从实战与源码角度出发,全面剖析Spring事务传播机制,帮助你答得有…...
