Description
1、问题描述
给定n个字符及其对应的权值,构造Huffman树,并进行huffman编码和译(解)码。
构造Huffman树时,要求左子树根的权值小于右子树根的权值。
进行Huffman编码时,假定Huffman树的左分支上编码为‘0’,右分支上编码为‘1’。
2、算法
构造Huffman树算法:
⑴、根据给定的n个权值(w1, w2, …, wn)构成n棵二叉树的集合F={T1, T2, …, Tn},其中每棵二叉树Ti中只有一个权值为wi的根结点
⑵、在F中选取两棵根结点的权值最小的树,作为左、右子树构造一棵新的二叉树,且置其根结点的权值为其左、右子树权值之和
⑶、在F中删除这两棵树,同时将新得到的二叉树加入F中
⑷、重复⑵, ⑶,直到F只含一棵树为止
Huffman编码算法:
⑴、从Huffman树的每一个叶子结点开始
⑵、依次沿结点到根的路径,判断该结点是父亲结点的左孩子还是右孩子,如果是左孩子则得到编码‘0’,否则得到编码‘1’,先得到的编码放在后面
⑶、直到到达根结点,编码序列即为该叶子结点对应的Huffman编码
Huffman译(解)码算法:
⑴、指针指向Huffman树的根结点,取第一个Huffman码
⑵、如果Huffman码为‘0’,将指针指向当前结点的左子树的根结点;如果Huffman码为‘1’,将指针指向当前结点的右子树的根结点
⑶、如果指针指向的当前结点为叶子结点,则输出叶子结点对应的字符;否则,取下一个Huffman码,并返回⑵
⑷、如果Huffman码序列未结束,则返回⑴继续译码
Input
第一行:样本字符个数,假设为n。
第二行,n个字符(用空格隔开)
第三行,n个字符对应的权值(用空格隔开)
第四行,待编码的字符串
第五行,待译码的Huffman码序列
Output
第一行,每个字符对应的Huffman编码(用空格隔开)
第二行,字符串对应的Huffman编码序列
第三行,Huffman码序列对应的字符串
Sample Input
4
a b c d
9 3 2 6
abcd
111001010
Sample Output
0 101 100 11
010110011
dcba
#include <iostream>
#include <string.h>
using namespace std;
#define MAXCODELEN 15
#define MAXHUFFMANCODENO 10
#define MAXCODESTRINGLEN 100
typedef struct
{
char c;
int weight;
int parent,lchild,rchild;
char code[MAXCODELEN];
}
HTNode,*HuffmanTree;
HTNode HT[2*MAXHUFFMANCODENO];
void Select(int i1,int *s1,int *s2)
{
unsigned int j,s;
s=0;
for (j=1;j<=i1;j++)
{
if (HT[j].parent==0)
{
if(s==0)
s=j;
if(HT[j].weight<HT[s].weight)
s=j;
}
}
*s1=s;
s=0;
for (j=1;j<=i1;j++)
{
if((HT[j].parent==0) && (j!=*s1))
{
if(s==0)
s=j;
if (HT[j].weight<HT[s].weight)
s=j;
}
}
*s2=s;
}
void CreateHuffmanTree(int n,char *c,int *w)
{
int i,m,s1,s2;
m=2*n-1;
for(i=1;i<=n;++i)
{
HT[i].c=c[i-1];
HT[i].weight=w[i-1];
HT[i].parent=0;
HT[i].lchild=HT[i].rchild=0;
}
for ( ;i<=m;++i)
{
HT[i].weight=0;
HT[i].parent=HT[i].lchild=HT[i].rchild=0;
}
for (i=n+1;i<=m;++i)
{
Select(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 HuffmanCoding(int n)
{
int i,j,m,c,f,start;
char cd[MAXCODELEN];
m=MAXCODELEN;
cd[m-1]=0;
for(i=1;i<=n;i++)
{
start=m-1;
for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)
{
if(HT[f].lchild==c)
cd[--start]='0';
else
cd[--start]='1';
}
for (j=0;j<m-start;j++)
HT[i].code[j]=cd[start+j];
HT[i].code[j]=0;
}
}
void ShowHuffmanCode(int n)
{
int i;
for(i=1;i<n;i++)
cout<<HT[i].code<<" ";
cout<<HT[i].code<<endl;
}
int ShowHuffmanEncode(int n,char *eString)
{
int i,j;
for (j=0;j<strlen(eString);j++)
{
for(i=1;i<=n;i++)
{
if(eString[j]==HT[i].c)
{
cout<<HT[i].code;
break;
}
}
if(i>n)
return 0;
}
cout<<endl;
return 1;
}
int ShowHuffmanDecode(int n,char *dString)
{
int i,c,Root;
Root=2*n-1;
c=Root;
for(i=0;i<strlen(dString);i++)
{
if((HT[c].lchild==0) && (HT[c].rchild==0))
{
cout<<HT[c].c;
c=Root;
}
if(dString[i]=='0')
{
if (HT[c].lchild==0)
return 0;
c=HT[c].lchild;
}
else
{
if(HT[c].rchild==0)
return 0;
c=HT[c].rchild;
}
}
cout<<HT[c].c<<endl;
return 1;
}
int main(int argc,char *argv[])
{
int i,SampleNo,weight[MAXHUFFMANCODENO];
char c[MAXHUFFMANCODENO],EncodeString[MAXCODESTRINGLEN],DecodeString[MAXCODESTRINGLEN];
cin>>SampleNo;
for(i=0;i<SampleNo;i++)
cin>>c[i];
for(i=0;i<SampleNo;i++)
cin>>weight[i];
CreateHuffmanTree(SampleNo,c,weight);
HuffmanCoding(SampleNo);
ShowHuffmanCode(SampleNo);
cin>>EncodeString;
ShowHuffmanEncode(SampleNo,EncodeString);
cin>>DecodeString;
ShowHuffmanDecode(SampleNo,DecodeString);
return 0;
}
1、问题描述
给定n个字符及其对应的权值,构造Huffman树,并进行huffman编码和译(解)码。
构造Huffman树时,要求左子树根的权值小于右子树根的权值。
进行Huffman编码时,假定Huffman树的左分支上编码为‘0’,右分支上编码为‘1’。
2、算法
构造Huffman树算法:
⑴、根据给定的n个权值(w1, w2, …, wn)构成n棵二叉树的集合F={T1, T2, …, Tn},其中每棵二叉树Ti中只有一个权值为wi的根结点
⑵、在F中选取两棵根结点的权值最小的树,作为左、右子树构造一棵新的二叉树,且置其根结点的权值为其左、右子树权值之和
⑶、在F中删除这两棵树,同时将新得到的二叉树加入F中
⑷、重复⑵, ⑶,直到F只含一棵树为止
Huffman编码算法:
⑴、从Huffman树的每一个叶子结点开始
⑵、依次沿结点到根的路径,判断该结点是父亲结点的左孩子还是右孩子,如果是左孩子则得到编码‘0’,否则得到编码‘1’,先得到的编码放在后面
⑶、直到到达根结点,编码序列即为该叶子结点对应的Huffman编码
Huffman译(解)码算法:
⑴、指针指向Huffman树的根结点,取第一个Huffman码
⑵、如果Huffman码为‘0’,将指针指向当前结点的左子树的根结点;如果Huffman码为‘1’,将指针指向当前结点的右子树的根结点
⑶、如果指针指向的当前结点为叶子结点,则输出叶子结点对应的字符;否则,取下一个Huffman码,并返回⑵
⑷、如果Huffman码序列未结束,则返回⑴继续译码
Input
第一行:样本字符个数,假设为n。
第二行,n个字符(用空格隔开)
第三行,n个字符对应的权值(用空格隔开)
第四行,待编码的字符串
第五行,待译码的Huffman码序列
Output
第一行,每个字符对应的Huffman编码(用空格隔开)
第二行,字符串对应的Huffman编码序列
第三行,Huffman码序列对应的字符串
Sample Input
4
a b c d
9 3 2 6
abcd
111001010
Sample Output
0 101 100 11
010110011
dcba
#include <iostream>
#include <string.h>
using namespace std;
#define MAXCODELEN 15
#define MAXHUFFMANCODENO 10
#define MAXCODESTRINGLEN 100
typedef struct
{
char c;
int weight;
int parent,lchild,rchild;
char code[MAXCODELEN];
}
HTNode,*HuffmanTree;
HTNode HT[2*MAXHUFFMANCODENO];
void Select(int i1,int *s1,int *s2)
{
unsigned int j,s;
s=0;
for (j=1;j<=i1;j++)
{
if (HT[j].parent==0)
{
if(s==0)
s=j;
if(HT[j].weight<HT[s].weight)
s=j;
}
}
*s1=s;
s=0;
for (j=1;j<=i1;j++)
{
if((HT[j].parent==0) && (j!=*s1))
{
if(s==0)
s=j;
if (HT[j].weight<HT[s].weight)
s=j;
}
}
*s2=s;
}
void CreateHuffmanTree(int n,char *c,int *w)
{
int i,m,s1,s2;
m=2*n-1;
for(i=1;i<=n;++i)
{
HT[i].c=c[i-1];
HT[i].weight=w[i-1];
HT[i].parent=0;
HT[i].lchild=HT[i].rchild=0;
}
for ( ;i<=m;++i)
{
HT[i].weight=0;
HT[i].parent=HT[i].lchild=HT[i].rchild=0;
}
for (i=n+1;i<=m;++i)
{
Select(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 HuffmanCoding(int n)
{
int i,j,m,c,f,start;
char cd[MAXCODELEN];
m=MAXCODELEN;
cd[m-1]=0;
for(i=1;i<=n;i++)
{
start=m-1;
for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)
{
if(HT[f].lchild==c)
cd[--start]='0';
else
cd[--start]='1';
}
for (j=0;j<m-start;j++)
HT[i].code[j]=cd[start+j];
HT[i].code[j]=0;
}
}
void ShowHuffmanCode(int n)
{
int i;
for(i=1;i<n;i++)
cout<<HT[i].code<<" ";
cout<<HT[i].code<<endl;
}
int ShowHuffmanEncode(int n,char *eString)
{
int i,j;
for (j=0;j<strlen(eString);j++)
{
for(i=1;i<=n;i++)
{
if(eString[j]==HT[i].c)
{
cout<<HT[i].code;
break;
}
}
if(i>n)
return 0;
}
cout<<endl;
return 1;
}
int ShowHuffmanDecode(int n,char *dString)
{
int i,c,Root;
Root=2*n-1;
c=Root;
for(i=0;i<strlen(dString);i++)
{
if((HT[c].lchild==0) && (HT[c].rchild==0))
{
cout<<HT[c].c;
c=Root;
}
if(dString[i]=='0')
{
if (HT[c].lchild==0)
return 0;
c=HT[c].lchild;
}
else
{
if(HT[c].rchild==0)
return 0;
c=HT[c].rchild;
}
}
cout<<HT[c].c<<endl;
return 1;
}
int main(int argc,char *argv[])
{
int i,SampleNo,weight[MAXHUFFMANCODENO];
char c[MAXHUFFMANCODENO],EncodeString[MAXCODESTRINGLEN],DecodeString[MAXCODESTRINGLEN];
cin>>SampleNo;
for(i=0;i<SampleNo;i++)
cin>>c[i];
for(i=0;i<SampleNo;i++)
cin>>weight[i];
CreateHuffmanTree(SampleNo,c,weight);
HuffmanCoding(SampleNo);
ShowHuffmanCode(SampleNo);
cin>>EncodeString;
ShowHuffmanEncode(SampleNo,EncodeString);
cin>>DecodeString;
ShowHuffmanDecode(SampleNo,DecodeString);
return 0;
}