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;
}

 

posted @ 2025-02-03 19:09  Annaprincess  阅读(33)  评论(0)    收藏  举报