二叉堆
一 二叉堆的性质
在二叉堆中,二叉堆被分为大根堆和小根堆,大根堆满足手元素最大,小根堆满足首元素最小。在二叉堆中满足一个节点的左右子节点都小于或大于它本身。
二 二叉堆的数组实现方式
1. 储存方式
我们通常借助数组实现二叉堆的操作,类似于满二叉树,在数组中,第x个元素的左子树在2x个,它的右子树在第 2x-1个。
2. 基础操作的实现
初始化二叉堆
void Init()
{
for (int i = 1; i < N; i++)
{
elem[i] = inf;
}
}
弹出头部节点
在弹出节点后我们让最后一个节点去到头部的位置,然后从上向下调整我们的关系
// 弹出头部节点后用最后一个节点去代替他,
void pop()
{
elem[1] = elem[num];
elem[num--] = inf;
ModifyFromTop(1);
// 从头部向下继续调整顺序
}
输入一个节点
输入节点的后我们先让他处在尾部的位置,然后从下向上去调整关系
void push(int x)
{
elem[++num] = x;
ModifyFromBottom(num);
}
从头部向下修改二叉堆
void ModifyFromTop(int x)
{
if(elem[x]==inf) return;
// 如果修改到了没有值的地方,说明超出范围,直接返回
int target = (elem[ls(x)]<elem[rs(x)])? ls(x): rs(x);
// 判断左右边的大小,若该节点小于存储左右子树中的较小数,那么进行交换
if(elem[x]>elem[target])
{
swap(elem[x],elem[target]);
ModifyFromTop(target);
}
}
从底部向上修改二叉堆
void ModifyFromBottom(int x)
{
if(x==1) return;
if(elem[x] < elem[father(x)])
{
swap(elem[x],elem[father(x)]);
ModifyFromBottom(father(x));
}
}
三 例题和解法
例题
思路
按照上面给的几种基础操作,并封装到一个结构体中去,得到我们的heap数据结构
解法
#include<stdio.h>
#include <string.h>
#include <iostream>
#define father(x) (x/2)
#define ls(x) (2*x)
#define rs(x) (2*x+1)
#define N 1000020
#define inf 1000000000
using namespace std;
struct heap
{
int num; // record the number of the elem in the heap
int elem[N];
void Init()
{
for (int i = 1; i < N; i++)
{
elem[i] = inf;
}
}
inline int top()
{
return elem[1];
}
void ModifyFromBottom(int x)
{
if(x==1) return;
if(elem[x] < elem[father(x)])
{
swap(elem[x],elem[father(x)]);
ModifyFromBottom(father(x));
}
}
void ModifyFromTop(int x)
{
if(elem[x]==inf) return;
int target = (elem[ls(x)]<elem[rs(x)])? ls(x): rs(x);
if(elem[x]>elem[target])
{
swap(elem[x],elem[target]);
ModifyFromTop(target);
}
}
void push(int x)
{
elem[++num] = x;
ModifyFromBottom(num);
}
void pop()
{
elem[1] = elem[num];
elem[num--] = inf;
ModifyFromTop(1);
}
}Heap;
inline int read()//快读
{
int sum=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' && ch<='9') {sum=sum*10+ch-'0';ch=getchar();}
return sum*w;
}
int main()
{
int n = read();
Heap.Init();
int op;
for (int i = 0; i < n; i++)
{
op = read();
if(op==1)
{
int x = read();
Heap.push(x);
}
else if (op==2)
{
printf("%d\n",Heap.top());
}
else
Heap.pop();
}
}