堆
#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;
}