堆(自定义)

#include <iostream>

using namespace std;

// 堆是一个完全二叉树

// 手写堆
// 1、插入一个数
// 2、求集合中最小值
// 3、删除最小值
// 4、删除任意一个元素
// 5、修改任意一个元素

// 堆的存储不同于链表的存储,堆的存储是用一个一维数组来存储的。
// 以小根堆为例,根节点为最小值,小于它的左儿子和右儿子。
// 根节点x存储在小标为1的数组里,左儿子存储在下标为2x的数组,右儿子存储在下标为2x+1的数组里。


const int N = 100010;

int n, m;
int h[N], sz;

// 堆里的交换操作,可在这里维护其他操作
void heap_swap(int a, int b)
{
	swap(h[a], h[b]);
}

// 使当前节点向下传递至正确位置
void down(int u)
{
	// 记录当前节点与左右儿子中最小值的下标
	int min = u;

	// 如果左儿子存在且左儿子对应值小于当前最小值,更新最小值下标
	if (u * 2 <= sz && h[u * 2] < h[min])
	{
		min = u * 2;
	}

	// 如果右儿子存在且右儿子对应值小于当前最小值,更新最小值下标
	if (u * 2 + 1 <= sz && h[u * 2 + 1] < h[min])
	{
		min = u * 2 + 1;
	}

	// 如果最小值下标不是当前节点,则当前节点往下交换至min处,递归向下
	if (min != u)
	{
		heap_swap(min, u);
		down(min);
	}
}


void up(int u)
{
	// 如果父节点存在且 当前节点对应值<父节点对应值,则当前节点值向上传递
	while (u / 2 && h[u] < h[u / 2])
	{
		heap_swap(u, u / 2);
		u = u / 2;
	}
}

int main()
{
	cin >> n;

	for (int i = 1; i <= n; i++)
	{
		cin >> h[i];
	}

	// 数组建堆
	for (int i = n / 2; i; i--)
	{
		down(i);
	}


	// 1、插入一个数x
	int x = 10;
	h[++sz] = x;
	up(sz);

	// 2、求集合中最小值
	h[1];

	// 3、删除最小值
	h[1] = h[sz];
	sz--;
	down(1);

	// 4、删除任意一个元素
	int k = 10;
	h[k] = h[sz];
	sz--;
	down(k), up(k); // down操作和up操作只能执行一个

	// 5、修改任意一个元素
	h[k] = x;
	down(k), up(k);


	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值