【数据结构】--- 堆的应用

 

 个人主页:星纭-CSDN博客

系列文章专栏 :数据结构

踏上取经路,比抵达灵山更重要!一起努力一起进步!

一.堆排序 

 在前一个文章的学习中,我们使用数组的物理结构构造出了逻辑结构上的堆。那么堆到底有什么用呢???

首先思考这样一个问题,假设给定一个随机的数组,如何将这个数组建堆(在不使用额外的空间的条件下)。

这个问题不难,只需用到向上调整算法即可。

int main()
{int a[] = { 4,2,8,1,5,6,9,7,3,2,23,55,232,66,222,33,7,1,66,3333,999 };int i = 1;for (i = 1; i < sizeof(a) / sizeof(a[0]); i++) {AdjustUp(a, i);}return 0;
}

通过调试不难发现此时已经是一个大堆了。

如果想要得到小堆,只需要更改向上调整函数即可。

得到了大堆之后,又如何将这个数组排序得到一个升序的数组呢???

因为在大堆中,堆顶的数据一定是最大的,可以先将堆顶数据和数组最后一个位置上的数据进行交换,不管此时最大的数据,只看前size-1这个数据,进行向下调整得到第二大的数据,再更倒数第二个位置上的数据进行交换,..........依次进行下去就会得到一个升序的数组。 

int main()
{int a[] = { 4,2,8,1,5,6,9,7,3,2,23,55,232,66,222,33,7,1,66,3333,999 };int i = 1;for (i = 1; i < sizeof(a) / sizeof(a[0]); i++) {AdjustUp(a, i);}int end = sizeof(a) / sizeof(a[0]) - 1;while (end > 0) {Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}return 0;
}

简单来说,升序,建大堆,降序,建小堆。这就是堆排序。

然后就是向下调整建堆。假设给定一个数组,使用二叉树的形式表示,如下图所示 

假设这个二叉树,对于根来说,其左子树是大堆,右子树也是大堆,而这整个二叉树并不是大堆,我们就可以使用向下调整来使其变成大堆。可是这样一个随机的数组肯定是不满足上述的条件的,那么该如何使用向下调整算法来使其变成大堆呢?

答案就是倒着调整。

假设我们从最后一个数据开始,一个节点是既可以看作大堆也可以看作小堆的,此时我们就不需要对其进行调整,对于完全二叉树来说,他的叶子节点都不需要调整,所以我们就需要调整倒数第一个非叶子节点。以上图举例,也就是第三层第二个节点,将它和它的孩子节点看作一个树,这样就可以调整了。

那么倒数第一个非叶子节点的下标该怎么求呢?

倒数第一个非叶子节点是最后一个节点父亲节点。而最后一个节点的下标是n-1。所以倒数第一个非叶子节点的下标就是(n-1-1)/ 2;

	for (int i = (n-1-1)/2; i >= 0; i--){AdjustDown(a, n, i);}

二.建堆的时间复杂度

既然有两种不同的建堆算法,那么采用哪一种算法来建堆是更加好的呢?

所以接下来算一算两个算法的时间复杂度 

对于一个完全二叉树而言,假设其高度是h,那么它的节点个数最少和最多情情况,分别是最后一层只有一个节点和一个满二叉树。

对于一个满二叉树来说总节点个数n和高度h的关系是

F(n) = 2^0 + 2^1 + 2^2 + ... + 2^(h-1) = 2^h - 1。

h = log2(n + 1)

对于最后一层只有一个节点的二叉树而言总节点个数和高度h的关系是

F(n) = 2^0 + 2^1 + 2^2 + ... + 2^(h-2) + 1 = 2^(h-1) - 1 + 1= 2^(h-1)。

h = log2(n) - 1

根据大O的渐进表示法,我们可以大致得到h = logN的。

这样我们就得到了h和N之间的关系。

1.向上调整

计算向上调整的时间复杂度,我们需要计算总共向上调整了几次。

T(h) = 2^1*1 + 2^2 * 2 + ... + 2^(h-2)*(h-2) + 2^(h-1)*(h-1).
2*T(h) =       2^2*1 + 2^3 * 2 + ... +         2^(h-1)*(h-2) + 2^h*(h-1).
-T(h) = 2^1 + 2^2 + ... +2^(h-1) - 2^h*(h-1).= 2^h  - 2 -2^h*(h-1)= 2^h(1-h+1) -2 T(h) = 2 + 2 ^ h * hT(N) = 2 + 2 * log(N) * N = O(N * logN)

向上调整的时间复杂度是N*logN.

2.向下调整

T(h) = 2^0*(h-1) + 2^1*(h-2) + ...             +2^(h-2) * 1
2 * T(h) =         2^1*(h-1) + 2^2*(h-2) + ... +2^(h-2) * 2+2^(h-1) * 1
T(h) = 2^1 + 2^2+...+2^(h-2) +2^(h-1) - (h-1)= 2^h - 2 - h + 1= 2^h - h - 1= N - logN - 1= O(N)

对比不难发现向下调整的时间复杂度算法更优。 

三.TopK问题

 TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
    比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。
对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能
数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:
1. 用数据集合中前K个元素来建堆
    前k个最大的元素,则建小堆
    前k个最小的元素,则建大堆
2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素    
将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。

利用此算法的时间复杂度是O(N)

 

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

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

相关文章

GO channel 学习

引言 单纯地将函数并发执行是没有意义的。函数与函数间需要交换数据才能体现并发执行函数的意义。 虽然可以使用共享内存进行数据交换&#xff0c;但是共享内存在不同的goroutine中容易发生竞态问题。为了保证数据交换的正确性&#xff0c;必须使用互斥量对内存进行加锁&#…

ASP.NET Core----基础学习06----将所有数据在页面中显示 布局页面的使用

文章目录 1. 将数据以list的形式展示在页面中2. 布局页面的使用3. 自定义设置视图文件是否需要加载的JS 1. 将数据以list的形式展示在页面中 step1:在接口文件中添加新的方法GetAllStudents&#xff08;&#xff09; step2:在mock的数据中添加方法GetAllStudents&#xff08;&a…

关于mogdb vs kingbase的测评 说明

上周5同事转了一个帖子给我&#xff0c;说某公众号写了一篇MogDB vs KingBase的文章测评。该博主使用sysbench测了一些场景&#xff0c;其中大部分场景Mogdb相比KingBase而言表现都要差一些&#xff0c;只有一个场景比kingbase高很多。 老实说第一眼看到这个文章&#xff0c;我…

谷歌Gemini产品大揭秘:AI新纪元即将到来!

谷歌在Google I/O大会上预告了五款备受瞩目的Gemini产品&#xff0c;预计于7月15日和7月18日发布。这些产品将包括新版Imagen3、Gemini定制GPT、个性化回应功能、预设提示词以及录音与Google Photos集成等。 AI-321 | 专注全球AI工具推荐的网站 Ai工具集 | 专注ai人工智能 | 集…

代码随想录算法训练营第37天

卡码网 52. 携带研究材料 链接 #include <iostream> #include <vector> using namespace std;int knapsack(int w, vector<int>& weight, vector<int>& value) {vector<int> dp(w 1, 0);for(int i 0; i < weight.size(); i) {for…

C语言指针超详解——强化篇

C语言指针系列文章目录 入门篇 强化篇 文章目录 C语言指针系列文章目录1. assert 断言2. 指针的使用和传址调用2. 1 strlen的模拟实现2. 2 传值调用和传址调用 3. 数组名的理解4. 使用指针访问数组5. 一维数组传参的本质6. 冒泡排序7. 二级指针8. 指针数组9. 指针数组模拟实现…

C语言 ——— 将一句英语短句中的单词进行倒置

目录 题目要求 代码实现 题目要求 将一句英语短句中的单词进行倒置&#xff0c;标点符号不倒置 如&#xff1a; 输入&#xff1a;"I like chongqing very much," 输出&#xff1a;"much, very chongqing like I" 代码实现 #include<stdio.h> #i…

MyBatis where标签替换WHERE 1 = 1会提升性能吗

MyBatis <where>标签替换WHERE 1 1会提升性能吗 查看项目早期数据库查询语句时&#xff0c;发现很多地方写了WHERE 1 1&#xff0c;怀疑这里有性能损失&#xff0c;想替换成<where>标签。 验证 已知索引 CREATE INDEX BP_LOG_BP_DATE_IDX ON QXX.BP_LOG (BP_…

java实战项目-学生管理系统(附带全套源代码及其登录注册功能的实现)--《进阶篇》

一、前言 新增了登录注册的功能&#xff0c;代码量可能会有点大&#xff0c;所有代码加起来差不多560行。这个项目对于小白来说肯定是一大难关了。文章中的每张图都是作者亲手绘制的&#xff0c;简单明了&#xff0c;如果大家认同作者&#xff0c;希望可以支持一下作者。全套源…

论文翻译 | LEAST-TO-MOST: 从最少到最多的提示使大型语言模型中的复杂推理成为可能

摘要 思维链提示&#xff08;Chain-of-thought prompting&#xff09;在多种自然语言推理任务上展现了卓越的性能。然而&#xff0c;在需要解决的问题比提示中展示的示例更难的任务上&#xff0c;它的表现往往不佳。为了克服从简单到困难的泛化挑战&#xff0c;我们提出了一种新…

快速在springboot项目中应用EasyExcel

目录 ​编辑一、介绍 二、准备工作 三、初始化项目 3.1 创建项目 3.2 引入依赖 3.3 创建数据库和数据表 3.4 编写application.properties文件 四、开始编写 4.1 目录结构 4.2 MyBatis配置类 4.3 用户实体类 4.4 mapper接口 4.5 编写数据操作文件 4.6 编写Service 业…

【Linux】03.权限

一、权限的概念 Linux下有两种用户&#xff1a;超级用户&#xff08;root&#xff09;、普通用户。 超级用户&#xff1a;可以在 linux 系统下做任何事情&#xff0c;不受限制普通用户&#xff1a;在linux下做有限的事情超级用户的命令提示符是“#”&#xff0c;普通用户的命…

字节算法岗面试,效率贼高

最近这一两周看到不少互联网公司都已经开始秋招提前批了。 不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c;帮助一些球友…

python--实验 11 模块

目录 知识点 模块基础 模块使用方式 自定义模块示例 模块的有条件执行 Python包结构 定义和导入包 常用第三方库及安装 实例代码 第三方库自动安装脚本 Python标准库介绍 PyInstaller 小结 实验 1.(基础题)制作文本进度条。 2.(基础题) 蒙特卡罗方法计算圆周率…

[GXYCTF2019]BabySQli

原题目描述&#xff1a;刚学完sqli&#xff0c;我才知道万能口令这么危险&#xff0c;还好我进行了防护&#xff0c;还用md5哈希了密码&#xff01; 我看到是个黑盒先想着搞一份源码 我dirsearch明明扫到了.git&#xff0c;算了直接注入试试看 随便输入了两个东西&#xff0c…

Type-C PD芯片:引领充电技术的新纪元

随着科技的飞速发展&#xff0c;人们对电子设备的依赖日益加深&#xff0c;对充电速度、效率和安全性的要求也越来越高。在这样的背景下&#xff0c;Type-C PD&#xff08;Power Delivery&#xff09;芯片应运而生&#xff0c;以其高效、安全、智能的特点&#xff0c;成为了充电…

vscode编译环境配置-golang

1. 支持跳转 如果单测函数上方不显示run test | debug test&#xff0c;需要安装Code Debugger&#xff08;因为以前的go Test Explorer不再被维护了&#xff09; 2. 单测 指定单个用例测试 go test -v run TestXXXdlv 调试 需要安装匹配的go版本和delve版本&#xff08;如…

Linux多线程编程-生产者与消费者模型详解与实现(C语言)

1.什么是生成者与消费者模型 生产者-消费者模型是并发编程中的经典问题&#xff0c;描述了多个线程&#xff08;或进程&#xff09;如何安全、有效地共享有限的缓冲区资源。在这个模型中&#xff0c;有两种角色&#xff1a; 生产者&#xff08;Producer&#xff09;&#xff1…

<数据集>光伏板缺陷检测数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;2400张 标注数量(xml文件个数)&#xff1a;2400 标注数量(txt文件个数)&#xff1a;2400 标注类别数&#xff1a;4 标注类别名称&#xff1a;[Crack,Grid,Spot] 序号类别名称图片数框数1Crack8688922Grid8248843S…

研究生发表期刊/会议必看,一文看懂A/B/C类和顶刊

主要看&#xff1a;中国计算机学会&#xff08;CCF&#xff09;推荐国际学术期刊 里面的划分等级 等级为&#xff1a;A类&#xff08;最难&#xff09;>B类&#xff08;中等难度&#xff09;>C类&#xff08;难度一般&#xff09; 本人这边计划&#xff1a;最低发C刊&a…