二叉堆

二叉堆简介

二叉堆是一种基础数据结构,对于其他数据结构来说,支持的操作有限,也就插入,查询,删除这一类。

二叉堆的结构

从二叉堆的结构说起,它是一棵二叉树,并且是完全二叉树,每个结点中存在一个权值。堆性质:父亲的权值不小于儿子的权值(大根堆)。同样的,我们可以定义小根堆。本文以大根堆为例。由堆性质,树根存的是最大值。对于堆的每个子树,它同样也是一个堆。

考虑使用一个序列h来表示堆,$h_i$的两个儿子分别是$h_{2i}$和$h_{2i+1}$,$1$是根节点:

h 的堆结构

来自于:OI Wiki

具体每个节点的对应关系如上图。


二叉堆的基本操作

插入操作

插入操作是指向二叉堆中插入一个元素,但是要保证插入这个元素后,这颗二叉树仍然满足堆的性质。最简单的实现方法就是从最下层的叶子节点插入,如果最下面一层已经满了,就新建一层,将插入的节点与他的父亲节点比较,如果当前节点的权值大于父亲节点的权值,那么就交换父亲节点与当前节点,直到符合二叉堆的要求或者是当前插入的节点转移到根节点。

二叉堆的插入操作

来自于:OI Wiki

void pushup(int x){
    if(x==1)
        return;
    if(h[x]>h[x>>1])
        swap(h[x],h[x>>1]);
    pushup(x>>1);
}
void push(int x){
    h[++cnt]=x;
    pushup(cnt);
}

删除操作

删除操作指的是删除根节点的操作,同样地,在删除根节点后,我们要保证这一个堆的完整性,并且使堆仍然保持原来的性质。如果直接删除根节点,那么整个堆会一分为二,不好处理,所以,我们考虑将插入操作倒序走一遍,首先将根节点与它权值最大的儿子交换,然后不停地像这样交换下去,最终到达叶子节点,被删除。

void pop(int x){
    if((x<<1)>cnt){
        h[x]=inf;
        return;
    }
    if(h[x<<1]>h[x<<1|1]){
        swap(h[x],h[x<<1]);
        pop(x<<1);
    }
    else{
        swap(h[x],h[x<<1|1]);
        pop(x<<1|1);
    }
}

查询操作

查询操作只限于查询一个堆的堆顶元素。直接输出二叉堆的根即可。


$\rm{STL}$库中的优先队列

在$\rm{STL}$中,有个存在priority_queue,翻译叫做优先队列,实际上就是二叉堆,它处于queue库中,下面是它的几种操作:

  • 建立优先队列(大根堆):priority_queue<int>q
  • 建立优先队列(小根堆):priority_queue<int,vector<int>,greater<int> >q;
  • 插入一个数:q.push(x)
  • 删除堆顶:q.pop()
  • 查询堆顶:q.top()
  • 判断堆是否为空:q.empty()
  • 查询堆的元素个数:q.size()

代码

来源:洛谷:P3378 【模板】堆(小根堆,变换比较符号即为大根堆)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef unsigned int uint;
typedef long long LL;
typedef unsigned long long uLL;
typedef __int128 int128;
typedef unsigned __int128 uint128;
typedef long double Ld;
#define reg register;
#define space putchar(' ')
#define enter putchar('\n')
#define PI 3.14159265358979323846
#define pb(x) push_back(x)
#define mp(a,b) make_pair(a,b)
#define fi first
#define se second
#define pr(x) cerr<<#x<<"="<<(x)<<endl
#define pri(x,lo) {cerr<<#x<<"={";for (int ol=0;ol<=lo;ol++)cerr<<x[ol]<<",";cerr<<"}"<<endl;}
#define inf 1000000000
#define INF 1000000000000000000
#define N 1010
#define M 1000010
// void gettime(){
// 	cerr<<"time:"<<(double)clock()<<"ms"<<endl;
// }
namespace Fast{
	template<typename T>inline void read(T &x){
		x=0;bool f=false;char c=getchar();
		while(c<'0'||c>'9'){if(c=='-')f=true;c=getchar();}
		while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
		if(f)x=~x+1;
	}
	template<typename T>inline void print(T x){
		int s[65],top=0;
		if(x<0)putchar('-'),x=~x+1;
		while(x)s[++top]=x%10,x/=10;
		if(!top)s[++top]=0;
		while(top)putchar(s[top--]+'0');
	}
	template<typename T,typename...Args>inline void read(T &x,Args&...others){
		read(x),read(others...);
	}
	template<typename T,typename...Args>inline void print(T x,Args...others){
		print(x),space,print(others...);
	}
	const double eps=1e-7;
	template<typename T>inline T Abs(T x){return x>0?x:-x;}
	template<typename T>inline T Max(T x,T y){return x>y?x:y;}
	template<typename T>inline T Min(T x,T y){return x<y?x:y;}
	template<typename T>inline T Fabs(T x){return x>eps?x:-x;}
	template<typename T>inline T Fmax(T x,T y){return x-y>eps?x:y;}
	template<typename T>inline T Fmin(T x,T y){return x-y<eps?x:y;}
	template<typename T>inline void addmod(T &x,T p){if(x>=p)x-=p;}
	template<typename T>inline void submod(T &x,T p){if(x<0)x+=p;}
}
using namespace Fast;
int h[M<<1],n,cnt;
void pushup(int x){
    if(x==1)
        return;
    if(h[x]<h[x>>1])
        swap(h[x],h[x>>1]);
    pushup(x>>1);
}
void push(int x){
    h[++cnt]=x;
    pushup(cnt);
}
void pop(int x){
    if((x<<1)>cnt){
        h[x]=inf;
        return;
    }
    if(h[x<<1]<h[x<<1|1]){
        swap(h[x],h[x<<1]);
        pop(x<<1);
    }
    else{
        swap(h[x],h[x<<1|1]);
        pop(x<<1|1);
    }
}
int main(){
	read(n);
    for(int i=1;i<=n;i++){
        h[i]=inf;
    }
    for(int i=1;i<=n;i++){
        int opt,x;
        read(opt);
        if(opt==1){
            read(x);
            push(x);
        }
        if(opt==2){
            print(h[1]);
            enter;
        }
        if(opt==3){
            pop(1);
        }
    }
	return 0;
}

 

文章标题:二叉堆
文章链接:https://www.laoguantx.top/%e4%ba%8c%e5%8f%89%e5%a0%86.html
文章内容仅供参考,其中可能会有部分内容参考、引用其他网站,转发请务必标注作者为 “老官童鞋gogo” ,原文链接为 https://www.laoguantx.top/%e4%ba%8c%e5%8f%89%e5%a0%86.html 。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇