概念
- 完全二叉树:若设二叉树的深度为 h,除第 h 层外,其它各层(1~h-1)的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边。
- 用数组表示(下标从 1 开始),则有:
arr[i]
的左孩子是arr[2*i]
,右孩子是arr[2*i+1]
;arr[i]
的父节点是arr[i/2]
。
- 大顶堆:每个结点的值都大于或等于其左右孩子结点的值。
- 小顶堆:每个结点的值都小于或等于其左右孩子结点的值。
操作
注:本节以小顶堆为例,记堆的大小为 n
。
首先定义一个堆。
class Heap {
private:
int arr[maxn];
int n;
void shift_up(int i);
void shift_down(int i);
public:
Heap() {
memset(arr, 0, sizeof(int) * maxn);
n = 0;
}
void push(int x);
void pop();
int top();
int size();
bool empty();
};
上浮
从当前结点开始,和它的父节点比较:
- 若比父节点小则交换,然后将当前节点下标更新为原父节点下标;
- 否则退出。
void shift_up(int i) {
while (i > 1 && arr[i] < arr[i>>1]) {
swap(arr[i], arr[i>>1]);
i >>= 1;
}
}
下沉
当前节点与其左右孩子(如果有的话)中较小者作比较:
- 若后者比父节点小则交换,并更新当前节点下标