前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C++实验】哈夫曼树与哈夫曼编码实验

【C++实验】哈夫曼树与哈夫曼编码实验

作者头像
哈__
发布2024-06-23 12:38:53
800
发布2024-06-23 12:38:53
举报
文章被收录于专栏:哈哈熊哈哈熊

问题描述:

利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的u信息收发编写一个哈夫曼码的编/译码系统。

基本要求:

(1)接收原始数据(电文):从终端输入电文(电文为一个字符串,假设仅由26个小写英文字母构成)。 (2)编码:利用已建好的哈夫曼树,对电文进行编码。

(3)打印编码规则:即字符与编码的一一对应关系。

(4)打印显示电文以及该电文对应的哈夫曼编码。

(5)接收原始数据(哈夫曼编码):从终端输入一串哈二进制哈夫曼编码(由

0和1构成)。

(6)译码:利用已建好的哈夫曼树对该二进制编码进行译码。

(7)打印译码内容:将译码结果显示在终端上。

直接上代码,大家可以自己运行测试。

代码语言:javascript
复制
#include<iostream>
using namespace std;
class HFMtreeNode
{
	public:
		HFMtreeNode()
		{
			this->lchild=-1;
			this->rchild=-1;
			this->parent=-1;
			this->weight=0;
		}
		int lchild;
		int rchild;
		int weight;
		int parent;
};
class HuffCode
{
	public:
		HuffCode(int size)
		{
			this->bit=new int[size];
			this->start=size-1;
		}
		int *bit;//长度至少容下26个小写英文字母 
		int start;
};
bool isNumStr(string str)
{
	int n=str.length();
	bool isNum_str =true;  
	for(int i=0;i<n;i++)
	{
		if(str[i]-'0'<0||str[i]-'0'>9)
		{
			isNum_str=false;
			break;
		}
	}
	return isNum_str;
}
void func()
{
	int Hash [26][2];//记录输入字符串中每个字符的权重, 
	int hash=0;
	int temp[26][2];//按权重不为0的顺序排列Hash中的字符 和字符位置 
	int number=0;//统计总共出现的字符 
	for(int i=0;i<26;i++)
	{
		for(int j=0;j<2;j++)
		{
			Hash[i][j]=0;
		}
	}
	cout<<"请输入要进行被构建的字符串:"; 
	string str,num_str;
	cin>>str;
	for(int i=0;i<str.length();i++)
	{
		if(Hash[str[i]-97][0]==0)
		{
			Hash[str[i]-97][1]=hash;
			hash++;
		}
		Hash[str[i]-97][0]+=1;
	}
	for(int i=0;i<26;i++)
	{
		if(Hash[i][0]!=0)
		{
			 cout<<char(i+97)<<"的权重为:"<<Hash[i][0]<<endl;
			 temp[number][0]=Hash[i][0];
			 temp[number][1]=i;
			 number++;
		} 
	}
	HFMtreeNode *hfm=new HFMtreeNode[2*number-1];
	HuffCode **code=new HuffCode*[number];//字符编码 
	for(int i=0;i<number;i++)
	{
		hfm[i].weight=temp[i][0];
		code[i]=new HuffCode(number);
	}
	//开始构建哈夫曼树 
	for(int i=0;i<number-1;i++)
	{
		int x1=0,x2=0,m1=1000,m2=1000;
		for(int j=0;j<number+i;j++)
		{
			if(hfm[j].parent==-1&&hfm[j].weight<m1)
			{
				m2=m1;
				x2=x1;
				m1=hfm[j].weight;
				x1=j;
			}
			else if(hfm[j].parent==-1&&hfm[j].weight<m2)
			{
				m2=hfm[j].weight;
				x2=j;
			}
		}
		hfm[x2].parent=number+i;
		hfm[x1].parent=number+i;
		hfm[number+i].lchild=x1;
		hfm[number+i].rchild=x2;
		hfm[number+i].weight=hfm[x1].weight+hfm[x2].weight;
	}
	//哈夫曼树构建完成 
	
	//开始构建编码
	int p,c;
	for(int i=0;i<number;i++)//有几个字符构建几个编码 
	{
		c=i;
		p=hfm[c].parent;
		while(p!=-1)
		{
			if(hfm[p].lchild==c) code[i]->bit[code[i]->start]=0;
			else code[i]->bit[code[i]->start]=1;
			code[i]->start--;
			c=p;
			p=hfm[c].parent;
		}
		code[i]->start++;
	} 
	//编码构建结束 
	cout<<"编码前的字符串:"<<str;
	cout<<endl<<"编码后:"<<endl;
	for(int i=0;i<number;i++)
	{
		cout<<char(temp[i][1]+97)<<":";
		for(int j=code[i]->start;j<number;j++)
		{
			cout<<code[i]->bit[j];
		}
		cout<<endl;
	}
	//打印编码 
	cout<<"原字符串经过转换后:";
	for(int i=0;i<str.length();i++)
	{
		int n=Hash[str[i]-97][1];
		int m=code[n]->start;
		for(int j=m;j<number;j++)
		{
			cout<<code[n]->bit[j];
		}
		cout<<" ";
	}
	
	//将数字编码通过树转回字母,通过对hfm的遍历,hfm[i]表示的字符和temp[i]表示的字符相同,可通过temp[i][1]+97,来表示这个字符 
	cout<<endl<<"----------------------------------------"<<endl;
	cout<<"请输入需要被转译的数字串:";
	cin>>num_str;
	int n=num_str.length();
	//开始对字符串进行转译 
	//首先判断字符串输入的是不是数字串 
	while(!isNumStr(num_str))
	{
		cout<<"您输入的不是数字编码,请从新输入:";
		cin>>num_str;
	}
	
	//对数字编码进行处理
	HFMtreeNode h=hfm[2*number-2];
	int pos=-1;//记录下标 
	string result="";
	for(int i=0;i<n;i++)
	{
			if(num_str[i]-'0'==0)
			{
				pos=h.lchild;
				if(pos==-1) 
				{
					result="错误!";
					break;
				}
				h=hfm[pos];
			}
			else if(num_str[i]-'0'==1)
			{	
				pos=h.rchild;
				if(pos==-1)
				{
					result="错误!";
					break;
				}
				h=hfm[pos];
			}
			else
			{
				result="错误!";
				break;
			}
		if(pos>=0&&pos<number) 
		{
			result+=char(temp[pos][1]+97);
			h=hfm[2*number-2];
			pos=-1;
		}
	} 
	if(h.parent!=-1) 
	{
		result="错误!";
	}
	cout<<"数字转译后的字符串为:";
	cout<<result;
}

int main()
{
	func();
	
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
短信
腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档