添加注释版本:
/* 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
输出: