添加注释版本:
/*
cout<<i<<endl<<" 结点 | data | weight | lchild | rchild | parent "<<endl;
for(int i=1;i<=m;++i)
{
cout<<i<<" | "<<HT[i].data<<" | "<<HT[i].weight<<" | "<<HT[i].lchild<<" | "<<HT[i].rchild<<" | "<<HT[i].parent<<endl;
}
*/
#include<iostream>
#include<stdio.h>
#include<string>
#include<cstring>
#include<algorithm>
#define MAX 0x3f3f3f3f
using namespace std;
typedef struct
{
char data;
int weight;
int parent;
int lchild;
int rchild;
bool tag;
}Huffnode,*HuffmanTree;
typedef struct
{
string *code;//存放字符的编码
char *data;//存放字符
int num;//存放一共有多少字符
}HuffmanCode;
void DisplayHuffmanCode(HuffmanCode &HC,int n)
{
for(int i=0;i<n;++i)
{
cout<<HC.code[i]<<endl;
}
}
void Select(HuffmanTree &HT,int index, int &s1, int &s2)
{
int min1=MAX;
int min2=MAX;
for(int i=1;i<=index;++i)
{
if(HT[i].parent==0&&HT[i].tag)
{
if(HT[i].weight<min1)
{
s1=i;
min1=HT[i].weight;
}
}
}
HT[s1].tag=0;//表明此节点已经被选中过
for(int i=1;i<=index;++i)
{
if(HT[i].parent==0&&HT[i].tag)
{
if(HT[i].weight<min2)
{
s2=i;
min2=HT[i].weight;
}
}
}
HT[s2].tag=0;
}
void CreatHuffmanTree(HuffmanTree &HT,int n)
{
/*n:待编码数有多少*/
if(n<=1)return;
int m=2*n-1; //计算节点个数
HT=new Huffnode[m+1];//0号单元未用,HT[m]表示根结点,从1开始存放数据
//初始化哈夫曼表
for(int i=1;i<=m;++i)
{
HT[i].lchild=0;
HT[i].rchild=0;
HT[i].parent=0;
HT[i].tag=1;
HT[i].data='\0';
}
//依次输入待编码的数据的权重
cout<<"请依次输入每一个字和它的权重:"<<endl;
for(int i=1;i<=n;++i)
{
scanf("%c",&HT[i].data);
getchar();
scanf("%d",&HT[i].weight);
getchar();
// cin>>HT[i].data>>HT[i].weight;
}
//构造 Huffman树
int s1,s2;
for(int i=n+1;i<=m;++i)
{
Select(HT,i-1,s1,s2);
//在已经有数据的哈夫曼节点中,选择两个双亲域为0,且权值最小的结点
//并返回它们在HT中的序号s1和s2
HT[s1].parent=i;
HT[s2].parent=i;
//表示从F中删除s1,s2
HT[i].lchild=s1;
HT[i].rchild=s2;
//s1,s2分别作为i的左右孩子
HT[i].weight=HT[s1].weight + HT[s2].weight;
//i 的权值为左右孩子权值之和
}
cout<<" 结点 | data | weight | lchild | rchild | parent "<<endl;
for(int i=1;i<=m;++i)
{
cout<<i<<" | "<<HT[i].data<<" | "<<HT[i].weight<<" | "<<HT[i].lchild<<" | "<<HT[i].rchild<<" | "<<HT[i].parent<<endl;
}
}
//根据创建的哈夫曼树,从叶子到根逆向求每个字符的赫夫曼编码,存储在编码表HC中
void CreatHuffmanCode(HuffmanTree HT, HuffmanCode &HC, int n)
{
/*n:代表编码个数*/
HC.code=new string[n+1]; //分配n个指向字符串的指针
HC.data=new char[n+1];
HC.num=n+1;//从1开始存
for(int i=1; i<=n; ++i)
{ //逐个字符求赫夫曼编码
int c=i; //哈夫曼表的下标
int f=HT[i].parent;
string cd="";
while(f!=0)
{ //从叶子结点开始向上回溯,直到根结点
if (HT[f].lchild==c)
{
cd+="0"; //结点c是f的左孩子,则生成代码0
}
else
{
cd+="1"; //结点c是f的右孩子,则生成代码1
}
c=f; //跟新孩子,找上一代
f=HT[f].parent; //继续向上回溯
}
reverse(cd.begin(),cd.end());
HC.code[i]=cd; //将求得的编码从临时空间cd复制到HC的当前行中
// cout<<cd<<endl;
}
cout<<"当前的哈夫曼编码表为:"<<endl;
for(int i=1;i<=n;++i)
{
HC.data[i]=HT[i].data;
cout<<i<<" | "<<HC.data[i]<<" | "<<HC.code[i]<<endl;
}
}
void Encoding(HuffmanCode HC,string str)
{
cout<<"编码结果为:"<<endl;
for(int i=0;i<str.length();++i)
{
for(int j=1;j<=HC.num;++j)
{
// cout<<"\nHC.data[j]==str[i]"<<HC.data[j]<<" "<<str[i]<<endl;
if(HC.data[j]==str[i])
{
cout<<HC.code[j];
break;
}
}
}
}
void Decoding(HuffmanCode HC,string str)
{
cout<<"解码结果为:"<<endl;
string temp="";
int postion=0;
for(int i=0;i<str.length();)
{
for(int j=1;j<=HC.num;++j)
{
int k=0;
// cout<<"\n当前查找的是:"<<HC.code[j];
for(;k<HC.code[j].length();++k)
{
// cout<<" HC.code[j][k]!=str[i] "<<HC.code[j][k]<<","<<str[i+k];
if(HC.code[j][k]!=str[i+k])
{
break;
}
}
// cout<<" k="<<k<<endl;
if(k==HC.code[j].length())
{
i+=HC.code[j].length();
cout<<HC.data[j];
break;
}
}
}
}
int main()
{
HuffmanTree HT;
HuffmanCode HC;
//构造赫夫曼树,输出各字符的赫夫曼编码
cout<<"\n请输入编码的个数:"<<endl;
int n=0;
cin>>n;
getchar();
CreatHuffmanTree(HT,n);
CreatHuffmanCode(HT,HC,n);
// 编码:输入字符序列,输出对应的赫码序列。
cout<<"\n请输入要编码的字符:"<<endl;
string e_str="";
getline(cin,e_str);
Encoding(HC,e_str);
// cout<<e_str<<endl;
// 译码:输入赫夫曼码序列,输出原始字符代码。
cout<<"\n请输入要解码的字符:"<<endl;
string d_str="";
getline(cin,d_str);
Decoding(HC,d_str);
}
未加注释清爽版:
#include<iostream>
#include<stdio.h>
#include<string>
#include<cstring>
#include<algorithm>
#define MAX 0x3f3f3f3f
using namespace std;
typedef struct
{
char data;
int weight;
int parent;
int lchild;
int rchild;
bool tag;
}Huffnode,*HuffmanTree;
typedef struct
{
string *code;
char *data;
int num;
}HuffmanCode;
void DisplayHuffmanCode(HuffmanCode &HC,int n)
{
for(int i=0;i<n;++i)
{
cout<<HC.code[i]<<endl;
}
}
void Select(HuffmanTree &HT,int index, int &s1, int &s2)
{
int min1=MAX;
int min2=MAX;
for(int i=1;i<=index;++i)
{
if(HT[i].parent==0&&HT[i].tag)
{
if(HT[i].weight<min1)
{
s1=i;
min1=HT[i].weight;
}
}
}
HT[s1].tag=0;
for(int i=1;i<=index;++i)
{
if(HT[i].parent==0&&HT[i].tag)
{
if(HT[i].weight<min2)
{
s2=i;
min2=HT[i].weight;
}
}
}
HT[s2].tag=0;
}
void CreatHuffmanTree(HuffmanTree &HT,int n)
{
if(n<=1)return;
int m=2*n-1;
HT=new Huffnode[m+1];
for(int i=1;i<=m;++i)
{
HT[i].lchild=0;
HT[i].rchild=0;
HT[i].parent=0;
HT[i].tag=1;
HT[i].data='\0';
}
cout<<"请依次输入每一个字和它的权重:"<<endl;
for(int i=1;i<=n;++i)
{
scanf("%c",&HT[i].data);
getchar();
scanf("%d",&HT[i].weight);
getchar();
}
int s1,s2;
for(int i=n+1;i<=m;++i)
{
Select(HT,i-1,s1,s2);
HT[s1].parent=i;
HT[s2].parent=i;
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight + HT[s2].weight;
}
}
void CreatHuffmanCode(HuffmanTree HT, HuffmanCode &HC, int n)
{
HC.code=new string[n+1];
HC.data=new char[n+1];
HC.num=n+1;
for(int i=1; i<=n; ++i)
{
int c=i;
int f=HT[i].parent;
string cd="";
while(f!=0)
{
if (HT[f].lchild==c)
{
cd+="0";
}
else
{
cd+="1";
}
c=f;
f=HT[f].parent;
}
reverse(cd.begin(),cd.end());
HC.code[i]=cd;
}
cout<<"当前的哈夫曼编码表为:"<<endl;
for(int i=1;i<=n;++i)
{
HC.data[i]=HT[i].data;
cout<<i<<" | "<<HC.data[i]<<" | "<<HC.code[i]<<endl;
}
}
void Encoding(HuffmanCode HC,string str)
{
cout<<"编码结果为:"<<endl;
for(int i=0;i<str.length();++i)
{
for(int j=1;j<=HC.num;++j)
{
if(HC.data[j]==str[i])
{
cout<<HC.code[j];
break;
}
}
}
}
void Decoding(HuffmanCode HC,string str)
{
cout<<"解码结果为:"<<endl;
string temp="";
int postion=0;
for(int i=0;i<str.length();)
{
for(int j=1;j<=HC.num;++j)
{
int k=0;
for(;k<HC.code[j].length();++k)
{
if(HC.code[j][k]!=str[i+k])
{
break;
}
}
if(k==HC.code[j].length())
{
i+=HC.code[j].length();
cout<<HC.data[j];
break;
}
}
}
}
int main()
{
HuffmanTree HT;
HuffmanCode HC;
//构造赫夫曼树,输出各字符的赫夫曼编码
cout<<"\n请输入编码的个数:"<<endl;
int n=0;
cin>>n;
getchar();
CreatHuffmanTree(HT,n);
CreatHuffmanCode(HT,HC,n);
// 编码:输入字符序列,输出对应的赫码序列。
cout<<"\n请输入要编码的字符:"<<endl;
string e_str="";
getline(cin,e_str);
Encoding(HC,e_str);
// 译码:输入赫夫曼码序列,输出原始字符代码。
cout<<"\n请输入要解码的字符:"<<endl;
string d_str="";
getline(cin,d_str);
Decoding(HC,d_str);
}
测试样例:
输入:
27
输入:
186 a 64 b 13 c 22 d 32 e 103 f 21 g 15 h 47 i 57 j 1 k 5 l 32 m 20 n 56 o 63 P 15 q 1 r 48 s 51 t 80 u 23 v 8 w 18 x 1 y 16 z 1
输入:
you are bad gay but laolao is not
输入:
1000111001000011111010001001011110000010101011011110000110101000111111000000000111011111011110101001101111010100111101110011111011010011101
输出:




