noj实验3.1 哈夫曼编/译码器

这是本人参考教材以后完成的,感觉这题难度不算很大,但是需要注意的细节较为多一点。在这里插入图片描述

#include <iostream>
#include <string>
#define N 100					//字符集大小最多为100个
#define M 2*N-1				//最多产生的节点个数
#define max_weight 10000			//设置的最大权值

using namespace std;

typedef struct					//定义哈夫曼树的结构体变量
{
	int weight;
	int parent;
	int LChild;
	int RChild;
}HuffmanTree;

HuffmanTree ht[M+1];		 	//弃用第0号位置,装载哈夫曼树的各节点
int coders[500]={0};				//装载对报文的编码
char decoders[100];				//装载对编码解码后的报文
char chars[100];				//装载输入的报文
int x=0,y=0;

void select(int w, int *s1, int *s2)		//在当前所有没有双亲节点的节点中找到权值最小的两个节点,分别给s1(最小),s2(次小)
{
	int i,j,t,flag;
	int min_weight;
	min_weight = max_weight;
	for(i=1;i<=w;i++)			//最小无双亲节点的节点的权值赋给s1
	{
		if(ht[i].parent!=0)
			continue;
		flag=ht[i].weight;
		if(flag<min_weight)
		{
			min_weight = flag;
			j=i;
		}
	}
	*s1 = j;
	min_weight = max_weight;		//次小的无双亲节点的节点的权值赋给s2
	for(i=1;i<=w;i++)
	{
		if(i==j)
			continue;
		if(ht[i].parent!=0)
			continue;
		flag=ht[i].weight;
		if(flag<min_weight)
		{
			min_weight = flag;
			t=i;
		}
	}
	*s2 = t;
}

void CrtHuffmanTree( int w[], int n)		//创建哈夫曼树
{
	int m,i;
	int s1,s2;
	for(i=1;i<=n;i++)				//对哈夫曼树初始化
		ht[i]={w[i],0,0,0};
	m=2*n-1;
	for(i=n+1;i<=m;i++)
		ht[i]={0,0,0,0};
	for(i=n+1;i<=m;i++)
	{
		select(i-1,&s1,&s2);			//挑选权值最小的节点编号,赋给s1,挑选次小的,赋给s2
		ht[i].weight=ht[s1].weight+ht[s2].weight;
		ht[s1].parent=i;
		ht[s2].parent=i;
		ht[i].LChild=s1;
		ht[i].RChild=s2;
	}
}

void transmit(char chars[], string code, int num[], int n, int m)	//将目标报文按照给定的字符对应关系转化为数组
{
	int i,j;
	for(i=0;i<m;i++)								//遍历目标报文的每一个字符
	{
		for(j=1;j<=n;j++)						//查找字符与数字的对应关系,然后转化为数字
		{
			if(code[i]==chars[j])
			{
				num[i]=j;
				break;
			}
		}
	}
}

void CrtHuffmanCode(int num)					//对报文每一个字符(已转化为数字)进行编码
{
	int i,c,p,w=0;
	int cd[100];
	c=num;p=ht[num].parent;
	while(p!=0)
	{
		if(ht[p].LChild==c)
			cd[w++]=0;
		else
			cd[w++]=1;
		c=p;
		p=ht[p].parent;
	}
	for(i=w-1;i>=0;i--)
		coders[x++]=cd[i];
}

void Decoder(int *t,int m)						//对目标编码进行解码,得到解码后的报文
{
	int c;
	if(coders[(*t)++]==0)
		c=ht[m].LChild;
	else
		c=ht[m].RChild;
	while(ht[c].LChild!=0&&ht[c].RChild!=0)
	{
		if(coders[(*t)++]==0)
			c=ht[c].LChild;
		else
			c=ht[c].RChild;
	}
	decoders[y++]=chars[c];
}

int main()
{
    int i,m,n,t;
    int weights[100],num[100];
    string code;
    cin>>n;
    for(i=1;i<=n;i++)
	cin>>chars[i];
    for(i=1;i<=n;i++)
	cin>>weights[i];
    cin>>code;
    m=code.size();								//报文长度
    CrtHuffmanTree(weights, n);						//构建哈夫曼树
    transmit(chars,code,num,n,m);					//将报文按照对应关系转化为数组
    for(i=0;i<m;i++)
	CrtHuffmanCode(num[i]);						//对转化成数组的报文编码
    for(t=0;t<x;)
	Decoder(&t,2*n-1);							//将已知编码解码成报文
    for(i=0;i<x;i++)
	cout<<coders[i];							//输出编码后的密码
    cout<<endl;
    for(i=0;i<y;i++)
	cout<<decoders[i];							//输出解码后的报文
    cout<<endl;
    return 0;
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值