【堆】概念+二叉堆模板

一.堆的概念:

堆通常可以被看做一棵树,它满足下列性质:
1.堆中任意节点的值总是不大于(不小于)其子节点的值;

2.堆是一棵完全树。
       将任意节点不大于其子节点的堆叫做最小堆或小根堆,而将任意节点不小于其子节点的堆叫做最大堆或大根堆。

常见的堆有二叉堆、左倾堆、斜堆、二项堆、斐波那契堆等等。

二叉堆是完全二叉树,它分为两种: 最大堆和最小堆。

最大堆:父结点的键值总是大于或等于任何一个子节点的键值。

最小堆: 父结点的键值总是小于或等于任何一个子节点的键值。


二.二叉堆直观图:


三.二叉堆的存储方式:

 二叉堆一般是通过“数组”实现的。“二叉堆的第一个元素”放在数组索引为0的位置,则父节点与子节点的关系如下:

索引为i的左孩子的索引为:(2*i+1);((i<<1)|1)

索引为i的右孩子的索引为:(2*i+2);((i<<1)+2)

索引为i的父节点的索引为:int((i-1)/2);( floor( (i-1)/2 ) )

但一般我们令第一个元素放在数组索引为1的位置,这样会更方便。

索引为i的左孩子的索引为:(2*i);      (i<<1)

索引为i的右孩子的索引为:(2*i+1);((i<<1)|1)

索引为i的父节点的索引为:int(i/2); (i>>1)( floor( i/2 ) )

 


四.二叉堆插入数据

以最大堆为例:

 

总结:

1.把要插入的的元素放在末尾。

2.与其父节点比较,若大于父节点,swap即可,直到父节点<1,此时再无父节点可换。


五.删除数据

还是以最大堆为例:

一般我们删除最大值或最小值,即根的元素。

总结:

1.根元素和末尾元素swap,再top--进行删除。

2. 父节点与两个子节点比较,令maxn=max(左孩子,右孩子)。若父节点<maxn,说明父节点没有能力守住这个位置,则swap(maxn,父节点)。直到子节点>top,即再无子节点可换,已经为最小子节点了。


六.大根堆代码实现插入与删除

功能:先输入一个数n,接着输入n个数,表示插入二叉堆中,最后输入一个数m,表示删除m个堆首。

样例输入:5

                  9 2 4 5 21

                  1

样例输出:21 9 4 2 5

                  9 5 4 2

//大根堆 

#include<bits/stdc++.h>
#define maxn 10001
using namespace std;
int tree[maxn<<1]; //左右孩子,数组要开2倍
int n; 
int top=0; //最大节点下标 
void push(int x){
	tree[++top]=x;
	int k=top;
	while((k>>1)>0 && tree[k]>tree[k>>1]){
		swap(tree[k],tree[k>>1]);
		k>>=1;
	} 
}
void pop(){
	swap(tree[1],tree[top]);
	top--;
	int k=1;
	while(1){
		int t=k<<1;
		if(tree[t]<tree[t+1]) t++;//左孩子变右孩子
		if(t>top) break;
		if(tree[k]<tree[t]) swap(tree[k],tree[t]);
		else break;
		k=t; 
		
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		int num;
		cin>>num;
		push(num);
	}
	for(int i=1;i<=top;i++) cout<<tree[i]<<" ";
	cout<<endl;
	//二叉堆删除,删堆首;
	int m;
	cin>>m;
	while(m--){
		pop();
	} 
	for(int i=1;i<=top;i++) cout<<tree[i]<<" ";
	
}

七.小根堆:

同理,与大根堆相反。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值