数据结构之堆——学习笔记

1.堆的简介:

 

接下来看一下堆的建立;

 

接下来是如何在堆中插入数据以及删除数据:

 

 

 

大根堆的插入操作类似只是改变了一下大于和小于符号,同时插入操作的时间复杂度为O(logn)。

 

 

 

 来看几个问题:

答案当然是不可以:

 

这样的话就能根据原堆的末尾数字的大小来判断是应该尝试将它往上还是下进行移动。

 来看看STL里面的优先队列:

 

 

 值得注意的是 用优先队列是没有clear操作的。

接下来看几道例题:

1.堆排序:

 

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+100;
int n,heap[N],x,len=0;
inline void up(int x){while(x>1 && heap[x]<heap[x/2]){swap(heap[x],heap[x/2]);x/=2;}
}
inline void down(int k){while(k+k<=len){int j=k+k;if(j+1<=len && heap[j+1]<heap[j]) ++j;if(heap[j]>=heap[k]) break;swap(heap[k],heap[j]);k=j;}
} 
int main(){cin>>n;for(int i=1;i<=n;i++){cin>>x;heap[++len]=x;up(len);}for(int i=1;i<=n;i++){cout<<heap[1]<<' ';swap(heap[1],heap[len]);--len;down(1);}return 0;
}

事实上用优先队列来做会非常的简单:

#include<bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int>>q;
const int N=1e5+100;
int n;
/*inline void up(int x){while(x>1 && heap[x]<=heap[x/2]){swap(heap[x],heap[x/2]);x/=2;}
}
inline void down(int x){while(x+x<=len){int y=x+x;if(y+1<=len && heap[y+1]<heap[y])  ++y;if(heap[y]>=heap[x]) break;swap(heap[y],heap[x]);x=y;}
}*/
int main(){cin>>n;for(int i=1;i<=n;i++){int x;cin>>x;q.push(x);}	for(int i=1;i<=n;i++){cout<<q.top()<<' ';q.pop();}return 0;
}

使用小根堆的话是需要背一下优先队列的写法,有一点长。

接下来看一下第二题:

合并数列:

 这道题目的数据范围如果给的很小的话其实可以直接考虑模拟做法,但是实际上这道题目并没有那么的简单,接下来看代码,我在上面给了注释。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+100;//这里的N要比序列的个数上限设置的更大
int n,len,m;//n个序列,len代表当前读入的堆的序列的个数,m是最后要输出的数字个数
struct xulie{int v,delta;//v代表某一序列当前的堆顶元素,delta代表对应序列的k值
}heap[N];
//对新读入的序列试着将他往上面排的函数
inline void up(int x){while(x>1 && heap[x].v<=heap[x/2].v){swap(heap[x],heap[x/2]);x/=2;}
}
//将堆首的元素试着往下排
inline void down(int x){while(x+x<=len){int y=x+x;if(y+1<=len && heap[y+1].v<heap[y].v)  ++y;if(heap[y].v>=heap[x].v) break;swap(heap[y],heap[x]);x=y;}
}
int main(){cin>>n;for(int i=1;i<=n;i++){int k,b;cin>>k>>b;heap[++len].v=b;heap[len].delta=k;up(len);}cin>>m;for(int i=1;i<=m;i++){cout<<heap[1].v<<' ';heap[1].v+=heap[1].delta;//输出堆顶序列这时候的值之后,对该序列的v值加一个delta并将加了之后的堆顶序列试着往下排down(1);}return 0;
}

这道题的做法还是很有意思的。

接下来看一下第三个题:

大富翁游戏:

 费了九牛二虎之力,可算是搞明白了。。。

代码如下:

#include<bits/stdc++.h>
using namespace std;
struct Info{int v,pos;
}heap1[100001],heap2[100001];
int n,m,len1,len2,s1[100001],s2[100001];
inline void up1(int k){while(k>1 && heap1[k].v<heap1[k/2].v){swap(heap1[k],heap1[k/2]);s1[heap1[k].pos]=k;s1[heap1[k/2].pos]=k/2;k/=2;}
}
inline void down1(int k){while(k+k<=len1){int j=k+k;if(j+1<=len1 && heap1[j+1].v<heap1[j].v)++j;if(heap1[k].v<=heap1[j].v) break;swap(heap1[k],heap1[j]);s1[heap1[k].pos]=k;s1[heap1[j].pos]=j;k=j;}
}
inline void up2(int k){while(k>1 && heap2[k].v>heap2[k/2].v){swap(heap2[k],heap2[k/2]);s2[heap2[k].pos]=k;s2[heap2[k/2].pos]=k/2;k/=2;}
}
inline void down2(int k){while(k+k<=len2){int j=k+k;if(j+1<=len2 && heap2[j+1].v>heap2[j].v)++j;if(heap2[k].v>=heap2[j].v) break;swap(heap2[k],heap2[j]);s2[heap2[k].pos]=k;s2[heap2[j].pos]=j;k=j;}
}
int main(){cin>>n;len1=len2=0;for(int i=1;i<=n;i++){heap1[++len1].v=100;heap1[len1].pos=i;s1[i]=len1;up1(len1);heap2[++len2].v=100;heap2[len2].pos=i;s2[i]=len2;up2(len2);}cin>>m;for(int i=1;i<=m;i++){int x;cin>>x;if(x==1){int y,z;cin>>y>>z;heap1[s1[y]].v+=z;up1(s1[y]);down1(s1[y]);heap2[s2[y]].v+=z;up2(s2[y]);down2(s2[y]);}else{cout<<heap2[1].v<<' '<<heap1[1].v<<endl;}}return 0;
}

这里代码中使用了两个堆,heap1heap2,分别用来维护最小堆和最大堆。s1s2 数组用来记录每个人在堆中的位置。代码中的堆结构的使用主要是为了在O(log n)的时间复杂度内找到当前最高和最低资金,以提高效率。在每次资金变动后,通过调整堆,保证堆顶元素分别是当前最小和最大资金。

最后一个题:动态中位数

这里是代码:

#include<bits/stdc++.h>
using namespace std;
int n;
priority_queue<int>a,b;
int main(){cin>>n;int x;cin>>x;a.push(x);cout<<a.top()<<' ';for(int i=1;i<=n/2;i++){int x,y,z=a.top();cin>>x>>y;if(x<z)a.push(x);else b.push(-x);if(y<z)a.push(y);else b.push(-y);if(a.size()-b.size()==3){b.push(-a.top());a.pop();} else if(b.size()-a.size()==1){a.push(-b.top());b.pop();}cout<<a.top()<<' ';}return 0;
}

 

  1. priority_queue 的使用:定义了两个优先队列(堆),ab。它们用于存储输入数字,其中 a 是最大堆,b 是最小堆。

  2. 第一个数字的处理:从输入中读取第一个数字 x,将其压入最大堆 a 中,然后输出当前中位数(即最大堆的堆顶元素)。

  3. 循环处理每个数字对(x,y):

    • 如果 x 小于当前中位数(即最大堆的堆顶元素 a.top()),则将 x 压入最大堆 a
    • 否则,将 -xx 的相反数)压入最小堆 b
    • 如果 y 小于当前中位数,则将 y 压入最大堆 a
    • 否则,将 -yy 的相反数)压入最小堆 b
  4. 调整堆大小:在每次插入后,检查两个堆的大小关系:

    • 如果最大堆 a 的大小比最小堆 b 大 3,将最大堆的堆顶元素弹出并压入最小堆 b
    • 如果最小堆 b 的大小比最大堆 a 大 1,将最小堆的堆顶元素弹出并取其相反数压入最大堆 a
  5. 输出中位数:每次插入后,输出当前中位数(即最大堆的堆顶元素 a.top())。

  6. 这段代码通过维护最大堆和最小堆,根据输入的数字实时调整堆,以便高效地计算中位数。在中位数的计算过程中,通过在两个堆之间调整元素,确保了两个堆的大小差距在一个合理的范围内。这样做的目的是为了避免在求中位数时需要对所有数据进行排序的开销,从而实现更加高效的中位数计算

希望这一篇学习笔记对读者有所帮助,让我们共同进步。

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

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

相关文章

每日一题——LeetCode1051.高度检查器

方法一 sort排序&#xff1a; 创建一个元素和heights一模一样的expect数组 &#xff0c;将expect数组从小到大进行排序&#xff0c;比较heights和expect相同位置不同的元素个数 var heightChecker function(heights) {var expect [],count0for(const n of heights){expect.…

Ubuntu同步两个剪切板

众所周知&#xff0c;ubuntu系统中有两套剪切板。第一个剪切板是用鼠标操作&#xff0c;鼠标选中则复制&#xff0c;点击鼠标中键则粘贴&#xff08;这个剪切板通常叫做——选择缓冲区&#xff09;。第二个剪切板则是真正的剪切板&#xff0c;使用ctrlc&#xff08;在终端中默认…

qml的操作 -- VS2022开发qml,

在使用VS开发软件的时候一般大型软件都会使用模组的方式。每个模组之间独立开发&#xff0c;关于qml写的UI模组也不例外&#xff0c;如果所有的qml都挤在一个文件夹下也不利于管理&#xff0c;维护起来也比较吃力。比较好的管理方法就是按照功能分布存放在不同的文件夹下。还有…

网络实训模拟考察题目和答案(华为eNSP综合实验考试)

拓扑中四个交换机五个路由器&#xff0c;共九个设备 答案是对应的九个脚本&#xff08;从设备命名到保存&#xff09; 全部复制粘贴后&#xff0c;从PC1、PC2都是能Ping通服务器的&#xff08;保及格&#xff09;&#xff0c;其他要求没检查 题目 VLAN信息 设备名称端口链路…

windows 查看所有端口占用情况

winR&#xff0c;调出cmd窗口&#xff1a; 输入命令 netstat -ano 内容太多&#xff0c;显示不全&#xff0c;怎么办? 输入下面命令 netstat -ano > d:\1.log 在d盘根目录下就产生了 输出文件 打开可以看到如下内容 活动连接协议 本地地址 外部地址 状…

【Android取证篇】小米手机OTG取证知识

【Android取证篇】小米手机OTG取证知识 小米手机OTG使用方法—【蘇小沐】 目录 1、OTG用途 2、手机连不上U盘 3、小米手机有没有OTG 4、手机usb调试找不到 5、MHL能否在HDMI输出视频的同时进行USB传输 1、OTG用途 使用OTG外接设备&#xff0c;需要使用和手机接口对应匹配的…

JSP+Servlet 重要知识点 (含面试题)

JSP是Servlet技术的扩展&#xff0c;本质上就是Servlet的简易方式。JSP编译后是“类servlet”。 这里提一句&#xff1a; jsp已经没有深入学习的必要了&#xff0c;除了维护老项目能用上一些&#xff0c;基本属于被淘汰的边缘了。Servlet还是有必要学习一下&#xff0c;比如sp…

【本科生通信原理】【实验报告】【北京航空航天大学】实验四:模拟信号的数字化及编码

目录 一、实验目的二、实验内容三、实验程序四、实验结果五、实验分析六、参考文献 一、实验目的 1、掌握低通信号的抽样及重建过程&#xff1b; 2、掌握PCM的编码及译码过程。 二、实验内容 共2问&#xff1a; 三、实验程序 1、 function q1() dt 0.001; % 时间分辨率…

如何本地搭建DolphinScheduler并无公网ip远程访问管理界面

文章目录 前言1. 安装部署DolphinScheduler1.1 启动服务 2. 登录DolphinScheduler界面3. 安装内网穿透工具4. 配置Dolphin Scheduler公网地址5. 固定DolphinScheduler公网地址 前言 本篇教程和大家分享一下DolphinScheduler的安装部署及如何实现公网远程访问&#xff0c;结合内…

通过cpolar在公网访问本地网站

通过cpolar可以轻松将本地网址映射到公网进行访问&#xff0c;下面简要介绍一下实现步骤。 目录 一、cpolar下载 二、安装 三、使用 3.1 登录 3.2 创建隧道 一、cpolar下载 cpolar官网地址&#xff1a;cpolar - secure introspectable tunnels to localhost 通过QQ邮箱…

网络请求 - 异步编程详解

一、概述 网络管理模块主要提供以下功能&#xff1a; HTTP数据请求&#xff1a;通过HTTP发起一个数据请求。WebSocket连接&#xff1a;使用WebSocket建立服务器与客户端的双向连接。Socket连接&#xff1a;通过Socket进行数据传输。 HTTP和WebSocket都是啥&#xff1f; 比如我…

MyBatis - 批量更新(update foreach)报错

在使用mybatis执行批量更新(update foreach)数据的时候报错如下&#xff1a; org.springframework.jdbc.BadSqlGrammarException: ### Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; c…

基于web3+solidity的众筹项目

基本配置&#xff1a;node、npm、yarn&#xff0c;安装ganache&#xff0c;chrome&#xff0c;chrome安装插件MetaMask&#xff0c; 主要功能&#xff1a;目的是实现一个简单的众筹平台&#xff0c;允许用户发起筹款项目、捐款、提出使用资金请求以及证明人证明。 部分合约&…

echarts 仪表盘进度条 相关配置

option {series: [{type: gauge,min: 0,//最大值max: 100, //最小值startAngle: 200,//仪表盘起始角度。圆心 正右手侧为0度&#xff0c;正上方为90度&#xff0c;正左手侧为180度。endAngle: -20,//仪表盘结束角度splitNumber: 100, //仪表盘刻度的分割段数itemStyle: {color…

深度学习|4.1 深L层神经网络 4.2 深层网络的正向传播

4.1 深L层神经网络 对于某些问题来说&#xff0c;深层神经网络相对于浅层神经网络解决该问题的效果会较好。所以问题就变成了神经网络层数的设置。 其中 n [ i ] n^{[i]} n[i]表示第i层神经节点的个数&#xff0c; w [ l ] w^{[l]} w[l]代表计算第l层所采用的权重系数&#xff…

day07 四数相加Ⅱ 赎金信 三数之和 四数之和

题目1&#xff1a;454 四数相加Ⅱ 题目链接&#xff1a;454 四数相加Ⅱ 题意 4个整数数组nums1&#xff0c; nums2&#xff0c; nums3&#xff0c; nums4的长度均为n&#xff0c;有多少个元组&#xff08;i&#xff0c;j&#xff0c;k&#xff0c;l&#xff09;使得 nums[…

Python如何生成个性二维码

Python-生成个性二维码 一、问题描述 通过调用MyQR模块来实现生成个人所需二维码。 安装&#xff1a; pip install myqr 二、代码实现 1.普通二维码 from MyQR import myqr # 普通二维码 myqr.run(wordshttp://www.csdn.net/mayi0312,save_nameqrcode.png ) 效果图&#…

@JsonFormat与@DateTimeFormat

JsonFormat注解很好的解决了后端传给前端的格式&#xff0c;我们通过使用 JsonFormat可以很好的解决&#xff1a;后台到前台时间格式保持一致的问题 其次&#xff0c;另一个问题是&#xff0c;我们在使用WEB服务的时&#xff0c;可 能会需要用到&#xff0c;传入时间给后台&am…

buuctf-Misc 题目解答分解109-111

109.[CFI-CTF 2018]webLogon capture 流量包分析&#xff0c; wireshark 打开 就这几个数据包&#xff0c;追踪http 进行url 解码 URL网址解码器 - 在线网址解码 得到flag CFI{1ns3cur3_l0g0n} 110.[GKCTF 2021]excel 骚操作 下载 excel 文件 &#xff0c;打开 发现点击其他地…

计算机Java项目|基于Springboot实现患者管理系统

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 文末获取源码 项目编号&#xff1a;KS-032…