一、堆(heap)
1.堆的分类
堆是计算机科学中一类特殊的数据结构的统称。堆可分为两种:大根堆和小根堆。一般喜欢用小根堆,以小根堆举例。
2.小根堆的性质
(1)小根堆中某个节点的值总是不小于其父节点的值,某个节点的值总是不大于其子结点的值。
(2)堆是一棵完全二叉树。所以可以静态数组来模拟堆。
3.向下更新与向上更新
int h[N], idx;
void down(int u) { //向下更新
int t = u;
if(u * 2 <= idx && h[u * 2] < h[t]) t = u * 2; //左结点更小
if(u * 2 + 1 <= idx && h[u * 2 + 1] < h[t] ) t = u * 2 + 1; //右结点更小
if(u != t) {
swap(h[u],h[t]); //交换
down(t); //继续向下更新
}
}
void up(int u) { //向下更新
while(u / 2 && h[u] < h[u / 2]) {
swap(h[u],h[u/2]);
n /= 2;
}
}
4.操作
添加一个数: h[++idx] = x; up(idx);
最小值: h[1];
删除最小值: h[1] = h[idx --]; down(1);
删除任意元素: h[k] = h[idx --]; down(k); up(k);
修改任意元素: h[k] = x; down(k) ; up (k);
注:一般只用前三种。
二、堆排序
int h[N], idx;
void down(int u) {
int t = u;
if (u * 2 <= idx && h[u * 2] < h[t]) t = u * 2;
if (u * 2 + 1 <= idx && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
if (u != t) {
swap(h[u], h[t]);
down(t);
}
}
void msort(int idx) { //复杂度O(n)
for(int i = idx / 2; i ; -- i) down(i);
}
三、STL 优先队列 priority_queue
优先队列本质是一个堆实现的。具有队列的所有特性,只是在这基础上添加了内部的一个排序。
1.定义
头文件:#include<queue>
priority_queue<int> q; 默认大根堆
priority_queue<int,vector<int>,greater<int> > q; 小根堆
2.操作方法
void s.push(k) 将元素放到队尾,自动排序,复杂度O(logn)
type s.top() 返回优先级最高的元素,但不删除。
void s.pop() 删除优先级最高的元素,复杂度O(logn)
int s.size() 返回优先队列元素的个数
bool s.empty() 检查优先队列是否为空
注:参考acwing