涉及到优先选择时用到堆,比如贪心法、k路归并、类dijkstra算法
堆的数组实现
数组x[1..n]下标从1开始(不使用x[0]),这样节点i的lchild = 2*i, rchild = 2*i+1, parent = i/2
最小堆性质:父节点<=它的子节点
关键函数siftup(n)用于在x[n]不满足堆性质时进行调整,调整只发生在i和它的父节点间,i不断向上;关键函数siftdown(n)用于在x[1]不满足堆性质时进行调整,调整只发生在i和它的较小子节点间,i不断向下。
void siftup(n) {
int i = n;
while (true) {
if (i == 1) break;
int p = i / 2;
if (x[p] <= x[i]) break;
swap(i, p);
i = p;
}
}
void siftdown(n) {
int i = 1;
while (true) {
int c = 2 * i;
if (c > n) break;
if (c + 1 <= n && x[c+1] < x[c])
c++;
if (x[i] <= x[c]) break;
swap(i, c);
i = c;
}
}
堆排序
用最大堆,将堆顶调换到数组尾、然后在去掉数组尾的堆上"整堆”
for i = [2,n]
siftup(i)
for i = [n,2]
swap(1, i)
siftdown(i-1)
siftdown(l,u)这种实现就是将siftdown()中的i=1变成i=l、跟n的比较变成跟u的比较
for i = [n/2, 1]
siftdown(i, n)
for i = [n,2]
swap(1, i)
siftdown(1, i-1)