真:pq用代码实现

还记得我之前写的关于数据结构的文章吗?脸那是piapia的打。。。没看的去看一看哈https://blog.youkuaiyun.com/weixin_43417464/article/details/113753894?spm=1001.2014.3001.5502

里面有我写的pq写法。。。但显而易见,我是认真瞎扯的

好吧,其实pq用代码实现是要用一个新的数据结构,叫做“堆”

二话少说,上定义!

堆,又名二叉堆
1.完全二叉树
2.小根堆 大根堆
小根堆:任意一个点的权值都小于他的子节点权值
大根堆:任意一个点的权值都大于他的子节点权值
3.操作:插入,删除,大小,堆顶
###就是这个堆不符合要求了,你就把他和他的根节点换一换,还不符合继续换...###

 记住了啊!必考题!

首先声明一下,堆是有STL模板的,是在头文件algorithm里的,具体用法参考下面:

堆的STL支持以下的基本操作:

make_heap(first, last, comp);

建立一个空堆;

push_heap(first, last, comp);

向堆中插入一个新元素;

top_heap(first, last, comp);

获取当前堆顶元素的值;

sort_heap(first, last, comp);

对当前堆进行排序;

但是,真男人,永远都不用STL!

没错,你没想错,就是用数组模拟堆!

直接上代码!!!!!!!!!!!!!!

/*
堆,又名二叉堆
1.完全二叉树
2.小根堆 大根堆
小根堆:任意一个点的权值都小于他的子节点权值
大根堆:任意一个点的权值都大于他的子节点权值
3.操作:插入,删除,大小,堆顶
###就是这个堆不符合要求了,你就把他和他的根节点换一换,还不符合继续换...### 
*/
#include<bits/stdc++.h>
using namespace std;
int heap[30005],number,n;//大小就是number,堆顶就是heap[1]
void insert(int x){//插入 pq.push();
	heap[++number]=x;
	int id=number;
	while(id!=1&&heap[id]<heap[id/2]){
		swap(heap[id],heap[id/2]);
		id/=2;
	}
}
void remove(){//删除 pq.pop();
	swap(heap[1],heap[number]);
	number--;
	int id=1;
	while(true){
		int son=-1;
		if(id*2+1<=number) son=heap[id*2]<heap[id*2+1]?id*2:id*2+1;
		else if(id*2==number) son=id*2;
		if(son==-1||heap[id]<heap[son]) break;
		swap(heap[id],heap[son]);
		id=son;
	}
}

做几道习题,巩固一下

一本通1369合并果子http://ybt.ssoier.cn:8088/problem_show.php?pid=1369

很简单一道优选队列题,但是我们就是要给自己施加难度:用数组模拟做

好像生搬硬套我给的代码就行了啊。。。

那就直接上代码

#include<bits/stdc++.h>
using namespace std;
int heap[30005],number,n;//大小就是number,堆顶就是heap[1] 
void insert(int x){//插入
	heap[++number]=x;
	int id=number;
	while(id!=1&&heap[id]<heap[id/2]){
		swap(heap[id],heap[id/2]);
		id/=2;
	}	
}
void remove(){//删除 
	swap(heap[1],heap[number]);
	number--;
	int id=1;
	while(true){
		int son=-1;
		if(id*2+1<=number) son=heap[id*2]<heap[id*2+1]?id*2:id*2+1;
		else if(id*2==number) son=id*2;
		if(son==-1) break;
		if(heap[id]<heap[son]) break;
		swap(heap[id],heap[son]);
		id=son;
	}
}
int main(){
	scanf("%d",&n);
	int sum=0;
	for(int i=0;i<n;i++){
		int x;scanf("%d",&x);
		insert(x);
	}
	for(int i=0;i<n-1;i++){
		int x=heap[1];remove();
		int y=heap[1];remove();
		insert(x+y);
		sum+=x+y;
	}
	printf("%d\n",sum);
	return 0;
}

再来一道,一本通1371看病http://ybt.ssoier.cn:8088/problem_show.php?pid=1371

但是这道题可就没那么简单了,我这会还是当个假男人吧这道题还是用pq的简单写法好一点

这涉及到了一个点:我要用结构体,可是这pq是个傻子,他不知道你是要怎么排

所以,这就是要用到:重载小于号!

格式是这样的:

struct 结构体名字{
    定义变量;
    friend bool operator < (const 结构体名字 a,const 结构体名字 b){
        排序方法;
    }
};
priority_queue<结构体名字> pq;

因为只有这样,这个傻子就会把你的排序方法把之前它的排序方式中的“<”替换成你的排序规则

上代码:

#include<bits/stdc++.h>
using namespace std;
int n,priority;char a[101];
struct node{
	char name[101];
	int priority;
	friend bool operator < (const node &a,const node &b){
		return a.priority<b.priority;
	}
};
priority_queue<node> pq;
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%s",&a);
		if(strcmp(a,"pop")==0)
			if(pq.empty()) printf("none\n");
			else{
				node p=pq.top();pq.pop();
				printf("%s %d\n",p.name,p.priority);
			}
		else{
			scanf("%s%d",a,&priority);
			node t;
			strcpy(t.name,a);
			t.priority=priority;
			pq.push(t);
		}
	}
	return 0;
}

 

 

 

 

 

文章最后,求个三连,但是不得不打个广告,当年明月写的《明朝那些事儿》是真的好看。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值