库函数:
#include<queue>
新知识:
1.函数重构:"<" 修改小于号的定义
用法:1.让数值的比较---->复数模的比较
2.建立小根堆,"<"定义转化 return left<right return1不交换!
bool operator <(Comeplex left, Comeplex right){
return left.re*left.re*+left.im*left.im < right.im*right.im+right.re*right.re ;
}
2.scanf 读入技巧
例如:我输入 3+i4; ,我要读入 3 ,4
scanf("%d+i%d",
3.优先队列:大根堆的构建方式(特殊大根堆) 前提
3.1前提:创建后,才能重构。
struct Comeplex{ //重构用到的类 a+bi
int re;
int im;
};
3.2重构函数:
bool operator < (Comeplex left, Comeplex right){
return left.re*left.re + left.im*left.im < right.im*right.im + right.re*right.re ;
}
3.3quq的其他操作使用法则
priority_queue<Comeplex> quq;
quq.push(放入Complex x)---->quq.push(x)
quq.size()
quq.empty //返回1 空
quq.top().re //返回最上端的 re部分
例题1KY196 复数集合
描述
一个复数(x+iy)集合,两种操作作用在该集合上: 1、Pop 表示读出集合中复数模值最大的那个复数,如集合为空 输出 empty ,不为空就输出最大的那个复数并且从集合中删除那个复数,再输出集合的大小SIZE; 2 Insert a+ib 指令(a,b表示实部和虚部),将a+ib加入到集合中 ,输出集合的大小SIZE; 最开始要读入一个int n,表示接下来的n行每一行都是一条命令。
输入描述:
输入有多组数据。 每组输入一个n(1<=n<=1000),然后再输入n条指令。
输出描述:
根据指令输出结果。 模相等的输出b较小的复数。 a和b都是非负数。
//踩坑
//1. 比较函数,多输入一个*,看来检查代码需要模块化检查
//2. 读懂题目,只要输入一次 n ! 后面都是指令
//3.
#include<cstdio>
#include <queue>
#include<string>
using namespace std;
struct Comeplex{ //重构用到的类 a+bi
int re;
int im;
};
bool operator <(Comeplex left, Comeplex right){
return left.re*left.re + left.im*left.im < right.im*right.im + right.re*right.re ;
}
int main() {
int n;
scanf("%d",&n);
priority_queue<Comeplex> quq; //大跟堆,怎么大? 重构函数 give "<" 比较复数!
for(int i=0;i<n;i++){
char str1[10];
scanf("%s",str1);
string str11 = str1;
//*********弹出
if(str11=="Pop"){ //****操纵1:弹出, 1 空不谈,2 不空的弹出
if(quq.empty()){ //队列空 quq.empty()
printf("empty\n");
}
else{
printf("%d+i%d\n",quq.top().re,quq.top().im);
quq.pop();
printf("SIZE = %d\n", quq.size());
}
}
//*********插入操作
else if(str11=="Insert"){ //quq.push() 插入操作
int re;
int im;
scanf("%d+i%d",&re,&im); //特别的读入方式
Comeplex a;
a.im=im;
a.re=re;
quq.push(a);
printf("SIZE = %d\n", quq.size());
}
}
}
哈夫曼树:KY188 哈夫曼树
算法思想:1.队列:小根堆 {一阶段:存储由小到大结点 二阶段:迭代结点}
一阶段:存放输入的结点
二阶段:每次取出小根堆两个点leaf1,leaf2 pop pop
迭代完成:----->push(leaf1+leaf2)
2.迭代公式: res= res + leaf1 + leaf2
res思路:
res = res + leaf1 + leaf2
res相当于是累加加入到构建哈夫曼树的结点权值之和
一上手打这个代码,我找到不理解的原因了,我看的视频是用特殊的案例讲解的,但是res的迭代过程我没理解,但是听你的讲解后,我才意识到问题的本质,求解哈夫曼树不仅仅可以用手计算,用程序计算其实就是归纳出了哈夫曼树最短路径的新求法,即累加所有结点和生成的新的结点
//踩坑:1.leaf1,2 pop读取,应该先top再pop
//踩坑:2.迭代中,忘了将1,2放入priority中!
#include <cstdio>
#include<queue>
using namespace std;
int main() {
int n;
scanf("%d",&n);
priority_queue<int>quq; //小根堆,用相反数
for(int i = 0; i<n; i++){ //小根堆建立
int leaf;
scanf("%d",&leaf);
quq.push(-leaf);
}
int res=0; //迭代结果:每次左子树都是累加的,右子树其实就加一个右结点。
while(quq.size()>1){
int leaf1,leaf2;
leaf1=quq.top();
quq.pop();
leaf2=quq.top();
quq.pop();
quq.push(leaf1+leaf2);
res=res+leaf1+leaf2;
}
printf("%d\n",-res);
}