堆排序

堆的作用:

 

堆的定义和堆的性质:

堆是一个完全二叉树,完全二叉树除了最后一层,其他层都是非空结点

小根堆:所有的父节点小于等于左右两个儿子,那就是在整棵树中,根节点是最小的

存储:用一维数组来存,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;
} 
复制代码
posted @   小志61314  阅读(41)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示