堆
堆
stl里的堆不能实现删除、修改任意一个元素,手写可以实现。
小根堆:堆顶最小。每一个根节点比左右子节点都小(stl里优先队列)
堆:

存储(用一维数组heap存储堆)
下标x(从1开始)
左孩子结点:2*x
右孩子结点 :2*x+1
下标关系如下表
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
1.手写堆

核心操作:
up 将该元素向上调整
down将该元素向下调整
利用up、down维护大根堆或小根堆。
作用:
1.插入一个数(插入到最后一个位置再向上调整)
heap[++size]=x;
up(size);
2.求集合中最小值(小根堆堆顶最小)
heap[1]
3.删除最小值
heap[1]=heap[size]
down(1)
size--;
4.删除任意一个元素(下标k)
heap[k]=heap[size]
size--;
up(k)
down(k)
5.修改任意一个元素
heap[k]=m
up(m)
down(m)
(1)堆排序

/*
从小到大输出前m小的数:用小根堆。每次输出堆顶,弹出堆顶。
所以一共两个操作:1.输出堆顶 2.弹出 堆顶,重新排成小根堆(需要利用down操作)
*/
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+6;
int heap[N];
int s;//堆大小
void down(int i){//向下,下标为i
int t=i;//t表示需要交换到的位置
if(i*2<=s&&heap[2*i]<heap[t]){//左子节点
t=2*i;
}
if(2*i+1<=s&&heap[2*i+1]<heap[t]){//右子节点
t=2*i+1;
}
if(t!=i){//需要交换
swap(heap[t],heap[i]);
down(t);//继续向下。递归。
}
}
int main(){
int m,n;
cin>>m>>n;
for(int i=1;i<=m;i++){
cin>>heap[i];//先放入heap数组
}
s=m;
for(int i=m/2;i;i--){//因为最下面一层无法向下,所以从倒数第二层向上每一个结点依次down调整
down(i);
}
while(n--){//最小的n个数
//每次输出堆顶,并弹出堆顶调整
cout<<heap[1]<<" ";
heap[1]=heap[s];
s--;
down(1);
}
return 0;
}
二.模拟堆

p-h映射:

//模拟小根堆
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+6;
int h[N];//堆
int ph[N];//堆中下标
int hp[N];//第几个插入
int s;//堆大小
int num;//第几个插入
void heap_swap(int a,int b) {//堆交换
//维护映射
swap(ph[hp[a]],ph[hp[b]]);
swap(hp[a],hp[b]);
//交换值
swap(h[a],h[b]);
}
void down(int a){//向下
int t=a;
if(a*2<=s&&h[2*a]<h[t]){
t=2*a;
}
if(1+a*2<=s&&h[1+2*a]<h[t]){
t=1+2*a;
}
if(t!=a){
heap_swap(t,a);
down(t);
}
}
void up(int a){//向上
while(a/2&&h[a]<h[a/2]){
heap_swap(a,a/2);
a=a/2;
}
}
int main(){
int n;
cin>>n;
string op;
int x,y;
while(n--) {
cin>>op;
if(op=="PM"){
//输出最小值(堆顶)
cout<<h[1]<<endl;
}
else if(op=="DM"){//删除堆顶
heap_swap(1,s);//堆顶和结尾交换
s--;
//维持堆
down(1) ;
}
else if(op=="I") {
//插入
cin>>x;
s++;//堆
num++;
h[s]=x;
ph[num]=s;
hp[s]=num;
up(s);//从最下面往上调整
}
else if(op=="D"){
//删除第x个插入元素
cin>>x;
int d=ph[x];
heap_swap(d,s);
s--;
up(d);
down(d);
}
else if(op=="C"){
// 修改第x个插入元素
cin>>x>>y;
int d=ph[x];
h[d]=y;
up(d);
down(d);
}
}
return 0;
}

浙公网安备 33010602011771号