堆
手写小根堆:堆一般就是完全二叉树,满足父节点小于等于子节点(大根堆相反)
数组存储堆:
1.父亲节点为 x ,则左右儿子节点分别为 2x , 2x + 1
2.插入一个数: head[++size] = x ; up(size);
3.求集合中最小值: head[1];
4.删除最小值: head[1] = head[size]; size--; down(1);
5.删除任意一个元素: head[k] = head[size]; size--;down(k);up(k);
6.修改任意一个元素: head[k] = x; down(k);up(k);
// AcWing: 堆排序
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const int N = 1e5 + 9;
int n, m, h[N], size;
// 将 根节点删除,并且寻找比根节点排名大 1 的数
void down(int u){
int t = u;
if(u * 2 <= size && h[2 * u] < h[t]) t = u * 2; //左儿子存在并且小于根节点
if(u * 2 + 1 <= size && h[u * 2 + 1] < h[t]) t = u * 2; //右儿子存在并且小于根节点
if(u != t){ // 如果存在比根节点小的数,交换,并且递归下去
swap(h[u], h[t]); // 因为交换后的数字可能还是比自己的子节点小,就要继续交换
down(t);
}
}
int main(){
cin>>n>>m;
size = n;
for(int i = 1; i <= n; i++) scanf("%d",a+i);
for (int i = n / 2; i; i--) down(i); //建堆
while(m--){
printf("%d ",head[1]); //根节点是最小的数字
h[1] = h[size];
size--;
down(1); //每次输出根节点之后都要删除根节点,将第二小的数移到根节点
}
return 0;
}
实现up和down操作
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e6 + 9;
int n, m, h[N], sizee ;
// 插入 从上到下
void down(int t){
int u = t;
if(2*t <= sizee && h[2*t] < h[u]) u = 2 * t; //左子树
if(2*t+1 <= sizee && h[2*t+1] < h[u]) u = 2 * t + 1 ; //右子树
if(t != u){swap(h[t],h[u]);down(u);} // 递归插入
}
//从下到上 //父节点 的值大于 子节点
void up(int t){if(h[t / 2] > h[t]) swap(h[t / 2] , h[t]), up(t / 2);}
int main(){
cin>>n;
while(n--){
int op , x;
cin>>op;
if(op == 1) scanf("%d",&x), h[++ sizee] = x, up(sizee); //建堆
else if(op == 2) printf("%d\n",h[1]);
else if(op == 3) h[1] = h[sizee--], down(1); // 删除原根节点
}
return 0;
}
注:OI蒻驹一枚,文章仅代表个人观点,如有不对,敬请指出,共同进步,谢谢。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律