【总结】2020暑假集训--二叉堆(未完待续)

一、概念

二叉堆是一种数组对象,它可以被视为一棵完全二叉树。树中每个结点与数组中存放该结点中值的那个元素相对应,如图。在这里插入图片描述
在这里插入图片描述

二、性质

设数组 A A 的长度为 l e n len ,二叉树的结点个数为 s i z e size s i z e l e n size≤len ,则 A [ i ] A[i] 存储二叉树中编号为 i i 的结点值( 1 i s i z e 1≤i≤size ),而 A [ s i z e ] A[size] 以后的元素并不属于相应的堆,树的根为 A [ 1 ] A[1] ,并且利用完全二叉树的性质,我们很容易求第 i i 个结点的父结点、左孩子、右孩子的下标,分别是 i / 2 i/2 2 i 2i 2 i + 1 2i+1 。(自己看图理解)
在这里插入图片描述
大根堆具有这样一个性质:对除根以外的每个结点i,A[fa(i)]≥A[i]。即除根结点以外,所有结点的值都不得超过其父结点的值,这样就推出,堆中最大元素存放在根结点中,且每一结点的子树中的结点值都小于等于该结点的值,这种二叉堆又称为“大根堆”;
反之,称为“小根堆”。

堆的操作

插入

图片理解

假如这是原始的堆
在这里插入图片描述
现在我们要插入一个13的节点,首先将他接在二叉树的后面,即7的右儿子在这里插入图片描述
可以发现他与他的父节点不满足大根堆的关系,所以交换他们
在这里插入图片描述
发现现在它和它的父节点仍然满足大根堆的性质,所以插入完成在这里插入图片描述
经过验证,新二叉堆依然满足性质,证明插入没问题

文字总结

转化为文字语言是:

  1. 在堆尾加入一个元素,并把这个结点置为当前结点。
  2. 比较当前结点和它父结点的大小
    如果如果当前结点大于父结点,则交换它们的值,并把父结点置为当前结点,继续转2。
    如果当前结点小于等于父结点,则转3。
  3. 结束。

代码实现

接下来是代码实现:

1.在堆尾加入一个元素,并把这个结点置为当前结点。

heap[++len]=a;

其中len为堆的元素个数

  1. 比较当前结点和它父结点的大小
    如果如果当前结点大于父结点,则交换它们的值,并把父结点置为当前结点,继续转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;
		}
	}
}

这是大根堆的实现,小根堆就请大家自己通过理解改一下了~

(未完待续)

删除

二叉堆主要支持的是删除根节点

依然是来几张图理解一下

图片理解

猜你喜欢

转载自blog.csdn.net/tanfuwen_/article/details/107465874
今日推荐