一、概念
二叉堆是一种数组对象,它可以被视为一棵完全二叉树。树中每个结点与数组中存放该结点中值的那个元素相对应,如图。
二、性质
设数组
的长度为
,二叉树的结点个数为
,
,则
存储二叉树中编号为
的结点值(
),而
以后的元素并不属于相应的堆,树的根为
,并且利用完全二叉树的性质,我们很容易求第
个结点的父结点、左孩子、右孩子的下标,分别是
、
、
。(自己看图理解)
大根堆具有这样一个性质:对除根以外的每个结点i,A[fa(i)]≥A[i]。即除根结点以外,所有结点的值都不得超过其父结点的值,这样就推出,堆中最大元素存放在根结点中,且每一结点的子树中的结点值都小于等于该结点的值,这种二叉堆又称为“大根堆”;
反之,称为“小根堆”。
堆的操作
插入
图片理解
假如这是原始的堆
现在我们要插入一个13的节点,首先将他接在二叉树的后面,即7的右儿子
可以发现他与他的父节点不满足大根堆的关系,所以交换他们
发现现在它和它的父节点仍然满足大根堆的性质,所以插入完成
经过验证,新二叉堆依然满足性质,证明插入没问题
文字总结
转化为文字语言是:
- 在堆尾加入一个元素,并把这个结点置为当前结点。
- 比较当前结点和它父结点的大小
如果如果当前结点大于父结点,则交换它们的值,并把父结点置为当前结点,继续转2。
如果当前结点小于等于父结点,则转3。 - 结束。
代码实现
接下来是代码实现:
1.在堆尾加入一个元素,并把这个结点置为当前结点。
heap[++len]=a;
其中len为堆的元素个数
- 比较当前结点和它父结点的大小
如果如果当前结点大于父结点,则交换它们的值,并把父结点置为当前结点,继续转2。
如果当前结点小于等于父结点,则转3。
while(now>1){
int fa=now>>1;
if(heap[fa]<heap[now]){
swap(heap[fa],heap[now]);
now=fa;
}
else{
break;
}
}
完整代码:
void Put(int a){ //加入节点
heap[++len]=a;
int now=len;
while(now>1){
int fa=now>>1;
if(heap[fa]<heap[now]){
swap(heap[fa],heap[now]);
now=fa;
}
else{
break;
}
}
}
这是大根堆的实现,小根堆就请大家自己通过理解改一下了~
(未完待续)
删除
二叉堆主要支持的是删除根节点
依然是来几张图理解一下