浙大数据结构:05-树9 Huffman Codes

news/2024/11/16 21:15:24/
这道题难度挺大,写起来较为费劲,这里我依然使用了STL库,使得代码量大幅减少不过百行,便于大家理解。
机翻:

1、条件准备 

数组存储字符对应频率,n,student存储输入多少字符,有多少学生测试。
wpl为最小带权路径长度,后边用到了multiset,分别来算最小带权路径长度和判断学生数据是否成立。后面看到代码再细说。
#include <iostream>
#include<string>
#include <set>
using namespace std;int num[128];//存储字符对应的频率
int n,student;//输入多少字符,有多少学生
int wpl;    //带权路径长度
multiset<pair<int,int>> s;//用来算最小的带权路径长度
multiset<string> se;//用来验证输入的数据是否符合要求
   主函数较为简单,先初始化一下,然后计算最小带权路径,然后输入学生,循环判断每个学生是否符合要求
int main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);init();wpl=minwpl();cin>>student;for(int i=0;i<student;i++){judge(wpl);}return 0;
}

2、init函数

输入字符数,然后存储字符和其频率,用num数组存储。
s集合存入数据对,第一个为出现的频率,第二个为0.具体含义后面再说。
void init()
{cin>>n;for(int i=1;i<=n;i++){char c;int a;cin>>c>>a;s.insert({a,0});num[c]=a;}
}

3、minwpl函数

如何计算最小带权路径长度呢?我们用哈夫曼树的构造方式来模拟:先取最小的两个合并成一个新的建立小子树,再从堆里选两个,以此类推直到最后合并成一棵树。但是这样只能生成带权路径最小的树,并没有算出带权路径是多少,我们这里采用数据对第二位来保存以该结点为根结点的最小带权路径,经过递推可以算出最终结果。我们具体来看一下。
先取堆顶放入左结点,删除堆顶再取堆顶放入右结点,删除堆顶。接下来准备插入t。
t的权值放在第一位,很好求,左右结点权值相加即可,
t为根节点的wpl初始也为左右结点权值相加,然后判断这个结点是否是后天计算的(非原始的),即第二位不为0,那么就加一下它的第二位,这样能使得权值较小的被多次相加也就算出了WPL.
这里建议画几颗树推一下,否则不是很好理解(我也是想半天想到的)
int minwpl()
{if(s.size()==1)return s.begin()->second;
//递归终点,就剩一个点了,就是根节点pair<int,int> left=*s.begin();//取最小s.erase(s.begin());//删除堆顶pair<int,int> right=*s.begin();//取最小s.erase(s.begin());//删除堆顶pair<int,int> t={left.first+right.first,left.first+right.first};
//建立新的结点if(left.second)t.second+=left.second;if(right.second)t.second+=right.second;s.insert(t);//插入return minwpl();//继续递归
}

4、judge函数

对于每个学生的数据,我们直接用每个字符的编码长度*该字符的权值再累加和求出wpl与我们的wpl进行比较即可。
如何判断前缀码是否有重的呢?我把每个输入的编码的所有前缀码存入集合se中,如果有字符的编码能在其中找到则前缀代码有问题,f=1。
最后输出。
PS:这里有个小bug,应该存一下所有编码最后再判断,但这题依然AC了
void judge(int miwpl)//判断wpl、是否重了,输出
{int w=0; //算当前student的wpl
se.clear();//清空一下
int f=0;//判断是否前缀码有重的for(int i=0;i<n;i++){char c;string s;cin>>c>>s;w+=s.size()*num[c];//算wplif(se.find(s)!=se.end())f=1;//不为其它函数的前缀码
//其实这里有bug,应该所有前缀码输入完再一个个判断,但这题还能ACse.insert(s); for(int j=1;j<=s.size();j++){se.insert(s.substr(0,j));//插入可能的前缀}}if(w!=miwpl){cout<<"No"<<endl;return ;}if(f){cout<<"No"<<endl;return ;}cout<<"Yes"<<endl;
}

5、总结

这道题难度非常大,我做了一下午,做完后发现网上很多代码都用C语言实现的,200行左右,我便把C++实现给大家分享一下,主要是给大家提供一些新的思路。
完整代码如下:
#include <iostream>
#include <string>
#include <set>
using namespace std;int num[128];
int n, student;
int wpl;
multiset<pair<int, int>> s;
multiset<string> se;
void init()
{cin >> n;for (int i = 1; i <= n; i++){char c;int a;cin >> c >> a;s.insert({a, 0});num[c] = a;}
}int minwpl()
{if (s.size() == 1)return s.begin()->second;pair<int, int> left = *s.begin();s.erase(s.begin());pair<int, int> right = *s.begin();s.erase(s.begin());pair<int, int> t = {left.first + right.first, left.first + right.first};if (left.second)t.second += left.second;if (right.second)t.second += right.second;s.insert(t);return minwpl();
}void judge(int miwpl) // 判断wpl、是否重了,输出
{int w = 0;se.clear();int f = 0;for (int i = 0; i < n; i++){char c;string s;cin >> c >> s;w += s.size() * num[c];if (se.find(s) != se.end())f = 1;se.insert(s);for (int j = 1; j <= s.size(); j++){se.insert(s.substr(0, j));}}if (w != miwpl){cout << "No" << endl; return;}if (f){cout << "No" << endl; return;}cout << "Yes" << endl;
}int main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);init();wpl = minwpl();cin >> student;for (int i = 0; i < student; i++){judge(wpl);}return 0;
}


http://www.ppmy.cn/news/1531373.html

相关文章

集群系统架构

ShedLock 是一个用于分布式环境下的锁机制&#xff0c;确保在同一时间点只有一个节点能够执行特定的定时任务。其核心原理是通过公共存储&#xff08;如数据库、Redis 等&#xff09;来实现锁的管理12。 具体来说&#xff0c;当一个任务在某个节点上开始执行时&#xff0c;该节…

node-red-L3-重启指定端口的 node-red

重启指定端口 目的步骤查找正在运行的Node.js服务的进程ID&#xff08;PID&#xff09;&#xff1a;停止Node.js服务&#xff1a;启动Node.js服务&#xff1a; 目的 重启指定端口的 node-red 步骤 在Linux系统中&#xff0c;如果你想要重启一个正在运行的Node.js服务&#x…

cubemx配置ADC

参考博客&#xff1a;https://blog.csdn.net/qq_29031103/article/details/119894077 生成代码&#xff1b; 接着编写代码&#xff1a; 1&#xff09;在main函数bsp初始化部分&#xff1b; 添加&#xff1a;HAL_ADCEx_Calibration_Start(&hadc1); 2&#xff09;在…

《The Graceful Dance of Fog》

《The Graceful Dance of Fog》 Fog, like an ethereal white silk, quietly blankets the expanse of heaven and earth. It resembles a mysterious dancer, moving in silence and enshrouding the whole world in its dreamlike embrace. "The fog entwines aroun…

【CSS】背景

background-color 颜色background-image 图像background-size 缩放background-repeat 平铺background-position 定位background-clip 裁剪区域background-origin 开始区域background-attachment 滚动方式 background-color 颜色 <style>div{width: 200px;height: 100px;…

react通过下拉框选择多个,并展示在下方的方式

以备后用&#xff0c;直接上代码&#xff1a; 一、方法&#xff1a; //查询学校一级部门列表async orgFirstLevelList() {let data {schoolId:this.state.schoolId};let depList await orgFirstLevelList(data);this.setState({depList: depList})}//删除所选部门deleteDep…

OpenHarmony(鸿蒙南向)——平台驱动指南【I2C】

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 概述 功能简介 I2C&#xff08;Inter Integrated Circuit&#x…

小川科技携手阿里云数据库MongoDB:数据赋能企业构建年轻娱乐生态

随着信息技术的飞速发展&#xff0c;企业在处理海量数据时所面临的挑战日益严峻。特别是在年轻娱乐领域&#xff0c;用户行为的多样性和数据量的激增对数据存储与分析技术提出了更高的要求。在此背景下&#xff0c;小川凭借其前瞻性的技术视野&#xff0c;选择了MongoDB作为其数…