您的位置:首页 > 编程语言 > C语言/C++

哈夫曼树——C++实现

2015-10-12 20:46 411 查看
#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息