#include <iostream>
using namespace std;
#define MAXBIT 10
#define MAXVALUE 10000
#define MAXLEAF 100
#define MAXNODE MAXLEAF*2-1
//定义哈夫曼树编码类型
typedef struct{
char bit[MAXBIT]; //存放叶子结点字符编码过后的二进制编码
int start; //存放叶子结点二进制编码在code[]数组里的起始数组位置
int length; //存放二进制编码的位数
}CodeType;
//定义哈夫曼树结点类型
typedef struct {
char ch; //字符
int weight; //哈夫曼树结点的权值
int lchild,rchild,parent; //哈夫曼树结点的左孩子,右孩子,父节点
}Htnode;
void createHFMTree(Htnode h[MAXNODE],int n); //构造哈夫曼树
void showCode(CodeType code[MAXNODE],Htnode h[MAXNODE],int n); //显示叶子的字符和其对应的二进制编码
void compileCode(char str[],int n,CodeType code[MAXLEAF],Htnode h[MAXNODE]);//输入字符串,得到二进制编码
void decompileCode(char num[],int n,CodeType code[MAXLEAF],Htnode h[MAXNODE]);//输入二进制编码得到字符串
void main(){
Htnode h[MAXNODE];
CodeType code[MAXLEAF];
char str[100]; //存放输入的需要编译的的字符串
char num[100]; //存放输入的需要编译的二进制字符串
int n; //输入的叶子结点数
//哈夫曼编码器
cout<<"-----------------哈夫曼编码器------------------\n";
cout<<"请输入叶子结点数:";
cin>>n;
createHFMTree(h,n);
showCode(code,h,n);
//哈夫曼译码器
cout<<"-----------------哈夫曼译码器------------------\n";
cout<<"请输入字符:\n";
cin>>str;
compileCode(str,n,code,h);
cout<<"请输入需要译码的编码:\n";
cin>>num;
decompileCode(num,n,code,h);
}
//构造哈夫曼树
void createHFMTree(Htnode h[MAXNODE],int n){
int i,j,m1,m2,s1,s2;
for(i=0;i<2*n-1;i++){ //所有节点初始化
h[i].weight=0;
h[i].parent=-1;
h[i].lchild=-1;
h[i].rchild=-1;
}
cout<<"请输入叶子节点的字符:";
for(i=0;i<n;i++){
getchar();
cin>>h[i].ch;
}
cout<<"请输入叶子节点的权重:";
for(i=0;i<n;i++){
getchar();
cin>>h[i].weight;
}
for(i=0;i<n-1;i++){
m1=m2=MAXVALUE; //m1和m2存储叶子结点权值的最小值和次小值
s1=s2=0; //s1和s2存储m1和m2的位置
for(j=0;j<n+i;j++){
if(h[j].weight<m1&&h[j].parent==-1){
m2=m1;
s2=s1;
m1=h[j].weight;
s1=j;
}
else if(h[j].weight<m2&&h[j].parent==-1){
m2=h[j].weight;
s2=j;
}
}
h[n+i].weight=h[s1].weight+h[s2].weight;//父结点的权重是左孩子和右孩子的权重之和
h[s1].parent=h[s2].parent=n+i;
h[n+i].lchild=s1;h[n+i].rchild=s2;
}
}
//显示叶子的字符和其对应的二进制编码
void showCode(CodeType code[MAXNODE],Htnode h[MAXNODE],int n){
int i,j,k,c,p;
CodeType cd;
for(i=0;i<n;i++){
code[i].length=0;
code[i].start=0;
k=code[i].start;
cd.start=n-1;
c=i;
p=h[c].parent;
while(p!=-1){ //有父节点
if(h[p].lchild==c) //孩子是父节点的左孩子
cd.bit[cd.start]='0';
else
cd.bit[cd.start]='1';
cd.start--;
c=p;
p=h[c].parent;
}
for(j=cd.start+1;j<n;j++,k++){
code[i].bit[k]=cd.bit[j];
code[i].length++; //length计算存放的二进制编码的位数
}
}
for(i=0;i<n;i++){ //输出每个叶子节点的哈夫曼编码
cout<<h[i].ch<<"的编码是:";
for(j=code[i].start;j<code[i].length;j++)
cout<<code[i].bit[j];
cout<<endl;
}
}
//输入字符串,得到二进制编码
void compileCode(char str[],int n,CodeType code[MAXLEAF],Htnode h[MAXNODE]){
for(int i=0;str[i]!='\0';i++){
for(int j=0;j<n;j++){
if(str[i]==h[j].ch){
for(int k=code[j].start;k<code[j].length;k++)
cout<<code[j].bit[k];
}
}
cout<<" ";
}
cout<<endl<<endl;
}
//输入二进制编码得到字符串
void decompileCode(char num[],int n,CodeType code[MAXLEAF],Htnode h[MAXNODE]){
int j=2*n-2; //哈夫曼树根结点的位置
for(int i=0;num[i]!='\0';i++){
if(num[i]=='0'){
j=h[j].lchild;
}
else if(num[i]=='1'){
j=h[j].rchild;
}
if(j<n){ //j大于等于n表示的都是除叶子结点以外的哈夫曼树结点
cout<<h[j].ch<<" ";
j=2*n-2;
}
}
cout<<endl;
}
哈夫曼树——C++实现
最新推荐文章于 2024-05-30 09:00:00 发布