手打堆求助,急!
查看原帖
手打堆求助,急!
677581
_Glassy_Sky_楼主2023/1/10 22:03
#include<bits/stdc++.h>
using namespace std;
int h[1000005];	
int n, op, x;
void up(int p)//已小顶堆为例,向上调整 
{
	while(p / 2 != 0)//表示父结点不空,不为0,也可以写成while(p / 2) 
	{
		if(h[p] < h[p / 2])//如果当前结点的值比父结点的值要小 
		{
			swap(h[p], h[p / 2]);//交换它们 
			p /= 2;//并且当前节点向根节点方向前进一步,向上跳一步,因为这一步存在,它带了logn 
		}
		else
			break; 		
	}	
}
void down(int p)//从当前节点p开始执行向下调整 
{
	while(2 * p <= n)//儿子节点还没有出界
	{ 
		int tmp = 2 * p;//初始,默认儿子记录为左儿子 
		if(tmp + 1 <= n && h[tmp] > h[tmp + 1])//如果左儿子>右儿子,且右儿子也没有出界默认儿子就记录为右儿子 
			tmp ++; 
		if(h[p] > h[tmp])
		{
			swap(h[p], h[tmp]);//交换父节点和默认儿子结点
			p = tmp;//当前节点向默认儿子节点方向跳一步 
		}
		else
			break; 
	}
}
void push(int x)//在堆中插入元素x 
{
	h[++ n] = x;//插入在堆位 
	up(n);//当前节点就是n号,从n号开始向上调整 
}
void pop()//删除堆顶元素 
{
	swap(h[1], h[n]);//首先交换堆顶和堆尾 
	n --;//堆的范围收缩一格 
	down(1);//从堆顶开始执行向下调整 
}
int main()
{
	int sum = 0;
	scanf("%d", &n);
	for(int i = 1; i <= n; i ++)
	{
		scanf("%d", &op);
		if(op == 1)//情况1 
		{
			scanf("%d", &x);
			push(x);//输入数字进堆 
			sum ++;//统计堆的数字个数 
		}
		if(op == 2) //情况2 
		{
			up(sum);//从sum(最后一个数的编号)开始,向上调整,变为小顶堆
			printf("%d\n", h[1]);//堆顶为最小数 
		}
		if(op == 3)//情况3
			pop();	
	}
	return 0;
} 
2023/1/10 22:03
加载中...