堆的笔记(模板)

首先是堆的定义:堆就是完全二叉树,从头到尾,头最小
下面是关于堆的代码实现:
首先是在数组中实现堆:

for(int i=n/2;i;i--)
down(i);
// O(n) 建堆
//down

down的意思是在一个头如果小于他的两个儿子那么进行交换,所以是下降的意思,
那么代码的意思是从二分之一的数开始进行对每个点的down操作,那么就遍历到每个数了。
在这里插入图片描述
每三个点成一个down的三点。所以只需要从n/2开始到 i=0 时即可,全部形成了头比两个儿子小的堆了。
down的代码:

void down(int u)
{
    
    
	int t=u;
	if(h[u]>h[u*2]&&u*2<=n)t=u*2;
	if(h[u]>h[u*2+1]&&u*2+1<=n)t=u*2+1;
	if(u!=t)
	{
    
    
		swap(h[u],h[t]);
		down(t);
	}
}

然后就是up操作了,如果当前点小于他的两个父亲节点那么进行交换操作:

void up(int u)
{
    
    
	while(h[u/2] >= h[u]  &&  u/2)
	{
    
    
		swap(h[u/2],h[u]);
		u>>=1;// 等价于u/2;
	}
}

最基本的操作还有,交换,因为在进行堆的操作时,还涉及到了堆的维护,由此
heap_swap();
// h[N]存储堆中的值, h[1]是堆顶,x的左儿子是2x, 右儿子是2x + 1
// ph[k]存储第k个插入的点在堆中的位置
// hp[k]存储堆中下标是k的点是第几个插入的

// h[N]存储堆中的值, h[1]是堆顶,x的左儿子是2x, 右儿子是2x + 1
// ph[k]存储第k个插入的点在堆中的位置
// hp[k]存储堆中下标是k的点是第几个插入的
void heap_swap(int i,int j)//   i,j分别表示他们所在堆中的位置
{
    
    
	swap(ph[hp[i]],ph[hp[j]]);	//先交换所插入的点所在堆中的位置。
	swap(hp[i],hp[j]);			//再交换记录两点插的顺序。
	swap(h[i],h[j]);			//最后交换两点的值。
}

第一个和第二个的swap位置不能够交换,第三个的位置可以随便。
再维护堆的时候还有很多操作:ex 删除某个点,直接swap再size–;再down就行了
再或者改变在这里插入图片描述
相关如上,操作不难,最重要的是函数的理解和运用,还有对堆的深刻理解。

猜你喜欢

转载自blog.csdn.net/weixin_51626694/article/details/116205201