1 二叉堆的原理
1.1 关键概念
- 属于完全二叉树,一般用数组表示。
- 又名优先队列,满足一般队列的操作原则:出队(删除)操作在队头(堆顶),入队(插入)操作在队尾(堆底)。
- 分为大根堆和小根堆,前者需满足堆中每个父节点的值大于等于左右子节点中的最大者,后者需要满足堆中每个父节点的值小于等于左右子节点的最小值。
- 父节点索引为i,则左右子结点为2i+1或2i和2i+2或2i+1;左右子节点为i,则其父节点为(i-1)/2或i/2(前者为下标为0开始,后者为下标为1开始)。
- 两个核心操作:down(下沉)、up(上浮)。
- 三个复合操作:建堆、插入、删除。
1.2 常用操作及其代码实现
以下标从1开始的大根堆来举例,小根堆操作类似。
堆用vector来存放,合法的堆所在的vector长度至少为1,因为下标为0的位置必须留空,真正的堆部分从1开始。
1.2.1 下沉操作
此操作的目的是将当前结点i下沉到正确的位置,每次下沉需要进行一次交换操作,具体的细节见代码。
//堆中的i结点进行下沉操作,使其落在正确的位置,返回此位置,若i结点不存在,则返回-1
int down(vector<int>& heap, int i){
int n = heap.size() - 1;
if(n <= 0 || i < 1 || i > n) return -1;
/*
不断尝试下沉操作,i为目标结点的位置,
随着下沉操作而增加,i到达叶子结点或者之前停止
*/
while(2*i <= n){
int l = 2*i;
int