题目描述:
手动输入一系列字符,自动统计字符出现的次数并作为该字符的权重,实现对应哈夫曼树的构造、编码、译码。
样例:
#include<bits/stdc++.h>
using namespace std;
#define maxval 10000
#define MaxBit 100 //哈夫曼编码的最大位数
typedef struct{
char ch;
int weight;
int flag;
int lchild,rchild,parent;
}HuffmanTree;
typedef struct{
char codeBit[MaxBit]; //位串
int start; //编码在位串中的起始位置
int weight;
char ch; //字符
}CodeNode;
void CreateHuffmanTree(HuffmanTree HuffTree[],int r[],int n){
int i,j,p1,p2,small1,small2;//x1,x2,
int w;
char c;
int m = 2*n-1;
for(i=0;i<m;i++){//初始化
HuffTree[i].parent=0;
HuffTree[i].lchild=-1;
HuffTree[i].rchild=-1;
HuffTree[i].weight=0;
}
i=0;
for(j=0;j<n;j++){
while(!r[i]) i++;
if(r[i]&&(i<255)&&(i>=0)){
HuffTree[j].ch=i;
HuffTree[j].weight=r[i];
}
i++;
// 哈夫曼树检测
// cout<<HuffTree[j].ch<<" "<<HuffTree[j].weight<<endl;
}
for(i=n;i<m;i++){
p1=0;p2=0;
small1=maxval;small2=maxval;
for(j=0;j<i;j++)
if(HuffTree[j].parent==0)
if(HuffTree[j].weight<small1){
small2=small1;
small1=HuffTree[j].weight;
p2=p1;
p1=j;
}
else if(HuffTree[j].weight<small2){
small2=HuffTree[j].weight;
p2=j;
}
HuffTree[p1].parent=i;
HuffTree[p2].parent=i;
HuffTree[i].lchild=p1; //最小转成新左孩子
HuffTree[i].rchild=p2; //次小转成新右孩子
HuffTree[i].weight=HuffTree[p1].weight+HuffTree[p2].weight;
}
}
//哈夫曼编码
void CalculateHuffmanCode(HuffmanTree HuffTree[],CodeNode HFCode[],int n){
int i,c,p;
CodeNode cd;
for(i=0;i<n;i++){
cd.start=n;
cd.ch=HuffTree[i].ch;
c=i;
p=HuffTree[i].parent;
while(p!=0){
cd.start--;
if(HuffTree[p].lchild==c) cd.codeBit[cd.start]='0'; //左'0'
else cd.codeBit[cd.start]='1'; //右'1'
c=p;
p=HuffTree[p].parent;
}
HFCode[i]=cd;
}
}
void decode(HuffmanTree HuffTree[],int m)//依次读入电文,根据哈夫曼树译码
{
int i,j=0;
char b[MaxBit];
char endflag='#'; //电文结束标志取2
i=m-1; //从根结点开始往下搜索
printf("输入发送的编码(以'#'为结束标志):");
printf("\n");
fflush(stdin);
gets(b);
printf("译码后的字符为");
while(b[j]!='#')
{
if(b[j]=='0')
i=HuffTree[i].lchild; //走向左孩子
else
i=HuffTree[i].rchild; //走向右孩子
if(HuffTree[i].lchild==-1) //tree[i]是叶结点
{
printf("%c",HuffTree[i].ch);
i=m-1; //回到根结点
}
j++;
}
printf("\n");
if(HuffTree[i].lchild!=-1&&b[j]!='#') //电文读完,但尚未到叶子结点
printf("\nERROR\n"); //输入电文有错
}//decode
int main(){
char *a=new char[1024];
string str; int t;
int r[1024]={0};
int N,n=0;//n为叶子节点数
printf("单词数目: \n");
scanf("%d",&N);
printf("输入字符串: \n");
for(int j=0;j<N;j++){
cin>>a;
while(*a!='\0'){ str+=*a; r[*a++]+=1;}
if(j!=(N-1)) { r[32]+=1; str+=" ";}
}
for(int i=0;i<255;i++)
if(r[i]) n++;
cout<<"叶子节点数: "<<n<<endl;
int m = 2*n-1;
HuffmanTree tree[m];
CodeNode code[n];
CreateHuffmanTree(tree,r,n);//建立哈夫曼树
CalculateHuffmanCode(tree,code,n);//哈夫曼编码
cout<<"哈夫曼编码: "<<endl;
for(int i=0;i<n;i++){
printf("%c: ",code[i].ch);
for(int j=code[i].start;j<n;j++)
printf("%c ",code[i].codeBit[j]);
printf("\n");
}
cout<<str<<"的哈夫曼编码为:"<<endl;
for(int i=0;i<str.length();i++){
for(int j=0;j<n;j++)
if(str[i]==code[j].ch)
for(int p=code[j].start;p<n;p++) printf("%c ",code[j].codeBit[p]);
}
printf("\n");
decode(tree,m);
return 0;
}