堆 Heap
- 完全二叉树:在二叉树中,若当前节点的下标为 i i i, 则其父节点的下标为 i / 2 i/2 i/2,其左子节点的下标为 i ∗ 2 i*2 i∗2,其右子节点的下标为 i ∗ 2 + 1 i*2+1 i∗2+1;
- 某个节点的值总是不大于或不小于其父节点的值
- 大根堆:父亲不小于儿子
- 小根堆:不大于
构建大根堆
-
从最后的子树开始 判断是不是最大的是爹
-
-
然后从下向上构建每个子树
vector<int>maxheap(n+1);
void MaxHeapInit(){
int len=maxheap.size();//maxheap用vector存的
int fa;
reforr(i,1,len/2){//从最后一个节点的爹开始
fa=maxheap[i];//fa是本次子树的爹
int son=i*2;//本次爹的左儿子
while (son<=len)
{
if(son<len&&maxheap[son]<maxheap[son+1])son++;//看右儿子是不是比左大 左右儿子和爹之中,最大的应该做爹
//son此时指向最大的儿子
if(fa>=maxheap[son])break;//爹比儿子大 不换
else{
//爹小了
maxheap[son/2]=maxheap[son];//儿子上浮
son*=2;//找儿子的儿子能不能上浮
}
}
maxheap[son/2]=fa;//本次儿子小于爹,把爹放到本次儿子的爹 归位
}
}
插入
- 堆的最后添加一个节点,然后沿着堆树上升
void insert(int x){
maxheap.push_back(x);//放到最后
int len=maxheap.size();
int son=len;
while (son>=1&&x>maxheap[son/2-1])//比爹大就换
{
maxheap[son-1]=maxheap[son/2-1];//爹下移
son/=2;
}
maxheap[son-1]=x;
}
删除
- 堆中每次只能删堆顶元素
- 删除堆顶后把最后子节点放到堆顶位置然后下移
void delete(){
int len=maxheap.size();
int x==maxheap[len-1];//最后一个子节点上移
int i=1,son=i*2;
while(son<=len){
if(son<=len&&x<maxheap[son])son++;//如果小于右树 优先向右树下移
if(x>=maxheap[son-1])break;
maxheap[i-1]=maxheap[son-1];
i=son;
son*=2;
}
maxheap[i]=x;
}
堆排序
- 无序数组->二叉堆
- 时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn) 不稳定排序
排序稳定性:排序后 2 个相等键值的顺序和排序之前它们的顺序相同
步骤
-
构造大根堆(升序)/小根堆(降序)
-
每次交换堆顶和最后一个元素,使堆顶元素(剩下中最大数)归位。
-
然后再构建根堆
void MaxHeapInit_range(int end){
int len=end;
int fa;
reforr(i,1,len/2){
fa=maxheap[i];
int son=i*2;
while (son<=len)
{
if(son<len&&maxheap[son]<maxheap[son+1])son++;
if(fa>=maxheap[son])break;
else{
maxheap[son/2]=maxheap[son];
son*=2;
}
}
maxheap[son/2]=fa;
}
}
void heap_sort(){
int len=maxheap.size()-1;
reforr(i,1,len){
//display();
MaxHeapInit_range(i);
swap(maxheap[1],maxheap[i]);
}
}
void solve(){
maxheap.push_back(0);
int n=7;
forr(i,1,n){
int num;
cin>>num;
maxheap.push_back(num);
}
heap_sort();
display();
}
priority_queue
- 底层二叉堆实现
- 头文件
#include<queue>
priority_queue<int>q;//默认大根堆
priority_queue<int,vector<int>,greater<int>>q;//小根堆
- 对结构体排序时,需要先定义比较符号
- 大根堆:小于号
struct pos{ int x,y; bool operator<(const pos&a)const{ return x<a.x; } };
- 小根堆:大于号
struct pos{ int x,y; bool operator>(const pos&a)const{ return x>a.x; } }; priority_queue<pos,vector<pos>,greater<pos>>q;
- 大根堆:小于号
题
P1090 合并果子
思路
- 贪心:每次选择最少的两个堆合并
- 用堆/优先队列
代码
之后填坑…