写一个哈夫曼码的编/译码系统,要求能对要传输的报文进行编码和解码。构造哈夫曼树时,权值小的放左子树,权值大的放右子树,编码时右子树编码为1,左子树编码为0. |
输入表示字符集大小为n(n <= 100)的正整数,以及n个字符和n个权值(正整数,值越大表示该字符出现的概率越大);输入串长小于或等于100的目标报文。 |
经过编码后的二进制码,占一行; 以及对应解码后的报文,占一行; 最后输出一个回车符 |
5 a b c d e 12 40 15 8 25 bbbaddeccbbb |
00011111110111010110110000 bbbaddeccbbb |
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXBIT 100
#define MAXNODE 1000
#define MAXNUM 100000
#define MAXWEIGHT 1000
using namespace std;
//编码结构体
typedef struct
{
int bit[MAXBIT];
int start;
}HCodeType;
//结点结构体
typedef struct
{
int weight;
int parent;
int lchild;
int rchild;
char value;
}HNodeType;
void HuffmanTree(HNodeType HuffNode[],int n)
{
int i,j;
//结点初始化
for(i=0;i<2*n-1;i++)
{
HuffNode[i].weight=0;
HuffNode[i].parent=-1;
HuffNode[i].lchild=-1;
HuffNode[i].rchild=-1;
HuffNode[i].value=-1;
}
//叶子结点的编码和权重
for(i=0;i<n;i++)
cin>>HuffNode[i].value;
for(i=0;i<n;i++)
cin>>HuffNode[i].weight;
for(i=0;i<n-1;i++)
{
//记录最小的两个权重
int m1,m2;
m1=m2=MAXWEIGHT;
//记录相应的下标
int x1,x2;
x1=x2=0;
/*找出所有结点中权值最小 无父节点的两个结点 并合并为一棵二叉树*/
for(j=0;j<n+i;j++)
{
if((HuffNode[j].weight<m1)&&(HuffNode[j].parent==-1))
{
m2=m1;
x2=x1;
m1=HuffNode[j].weight;
x1=j;
}
else if((HuffNode[j].weight<m2)&&(HuffNode[j].parent==-1))
{
m2=HuffNode[j].weight;
x2=j;
}
}
//找到x1 x2的父节点信息
HuffNode[x1].parent=n+i;
HuffNode[x2].parent=n+i;
HuffNode[n+i].weight=HuffNode[x1].weight+HuffNode[x2].weight;
HuffNode[n+i].lchild=x1;
HuffNode[n+i].rchild=x2;
}
}
//解码
void decoding(char str[],HNodeType hufTree[],int n)
{
int num=2*n-1;//结点个数
int i=0;
int temp;
while(i<(int)strlen(str))
{
temp=num-1;//根节点下标
while((hufTree[temp].lchild!=-1)&&(hufTree[temp].rchild!=-1))
{
if(str[i]=='0')
temp=hufTree[temp].lchild;
else
temp=hufTree[temp].rchild;
i++;
}
printf("%c",hufTree[temp].value);
}
}
int main()
{
HNodeType HuffNode[MAXNODE];
//编码结构体数组 和 临时变量来存放求解编码时的信息
HCodeType HuffCode[MAXBIT],cd;
int n,i;
scanf("%d",&n);
HuffmanTree(HuffNode ,n);
for(i=0;i<n;i++)
{
cd.start=n-1;
int cur=i;
int p=HuffNode[cur].parent;
while(p!=-1)//父节点存在
{
if(HuffNode[p].lchild==cur)
cd.bit[cd.start]=0;
else
cd.bit[cd.start]=1;
cd.start--;//求编码的低一位
cur=p;
p=HuffNode[cur].parent;
}
//保存求出的每个叶节点的哈夫曼编码和编码的起始位
for(int j=cd.start+1;j<n;j++)
HuffCode[i].bit[j]=cd.bit[j];
HuffCode[i].start=cd.start;
}
char code[1000];
scanf("%s",code);
for(i=0;i<(int)strlen(code);i++)
{
for(int j=0;j<n;j++)
{
if(code[i]==HuffNode[j].value)
{
for(int k=HuffCode[j].start+1;k<n;k++)
printf("%d",HuffCode[j].bit[k]);
}
}
}
printf("\n");
cout<<code<<endl;
return 0;
}
/*自底向上层层判断 若在父节点左侧 置0 在右侧 置1 最后输出生成的编码*/