堆排序
堆的作用:
堆的定义和堆的性质:
堆是一个完全二叉树,完全二叉树除了最后一层,其他层都是非空结点
小根堆:所有的父节点小于等于左右两个儿子,那就是在整棵树中,根节点是最小的
存储:用一维数组来存,1号点为根节点
down和up的操作:
应用原理:所有的父节点<=两个子节点
down是往下操作,up是往上操作
down操作:(与子节点的最小值进行交换)
up操作:(与父节点进行比较,如果小于父节点则交换)
用size表示当前堆的大小,heap来维护这个一维数组:
插入一个数,那直接在数组后面加一个数就完事了
求集合中的最小值:那直接就是堆顶元素
删除最小值:最小值是堆顶元素,也就是一维数组中对应的第一个,不好直接删除,那把最后一个覆盖到第一个上。删除最后一个,然后再进行一次down的操作
删除任意一个:和刚刚的删除最小值一样的思路,然后分类讨论不变,变大,变小,可以先down一遍再up一遍,因为如果变大那就往下走,如果变小,down不下去啊,那直接往上走,其实看似写两个,实则执行一个
具体的操作代码:
在代码实现的时候,一定要时刻记得是用一维数组来维护的,之前我忘记了,看代码看的我一脸懵圈,呜呜呜
下面上代码,一些细节代码中有:
#include<iostream> using namespace std; const int N=1e5+10; int h[N],s;//用一维数组来维护堆,用s来表示当前堆的大小 void down(int u) { int t=u;//记录一下当前最小编号 if(u*2<=s&&h[t]>h[u*2]) t=u*2;//经过这一步最小值的编号已经有可能产生变化 if(u*2+1<=s&&h[t]>h[u*2+1]) t=u*2+1;//目的就是找出t是三个编号中最小的那个 if(u!=t) { swap(h[u],h[t]); down(t); } } int main(){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>h[i]; s=n; for(int i=n/2;i;i--) down(i); while(m--)//要求前m个最小的,先输出最小的,然后删除,然后再输出最小的 { printf("%d ",h[1]); h[1]=h[s]; s--; down(1); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具