
{
inti;
HT=newHTNode[m];
for(i=0;i<m;i++)
{
HT[i].weight=0;
HT[i].parent=-1;
HT[i].lchild=-1;
HT[i].rchild=-1;
}
}
//****************************************
//从n个结点中选取最小的两个结点
//****************************************
void SelectMin(HuffmanTree &HT,intn,int &min1,int &min2)
{
typedefstruct
{
intNewWeight;//存储权
intp;//存储该结点所在的位置
}TempNode,*TempTree;
TempTreeTT=new TempNode[n];
inti,j;
j=0;
for(i=0;i<n;i++)
{
if(HT[i].parent==-1&& HT[i].weight!=0)
{
TT[j].NewWeight=HT[i].weight;
TT[j].p=i;
j++;
}
}//将HT中没有双亲的结点存储到TT中
intm1,m2;
m1=m2=0;
for(i=0;i<j;i++)
{
if(TT[i].NewWeight<TT[m1].NewWeight)//此处不让取到相等,是因为结点中有相同权值的时候,m1取最前的
那个。
m1=i;
}
for(i=0;i<j;i++)
{
if(m1==m2)
m2++;//当m1在第一个位置的时候,m2向后移一位
if(TT[i].NewWeight<=TT[m2].NewWeight&& i!=m1)//此处取到相等,是让在结点中有相同的权值的时候,
//m2取最后的那个。
m2=i;
}
min1=TT[m1].p;
min2=TT[m2].p;
}
/*创建哈夫曼树*/
void CreateHaffmanTree(HuffmanTree&HT,int n)
{
inti;
intm;
intmin1,min2;
if(n<=1)
cout<<"ParameterError!";
m=2*n-1;//哈夫曼树中结点的个数
InitHuffmanTree(HT,m);
for(i=0;i<n;i++)
{
cin>>HT[i].weight;
}
for(i=n;i<m;i++)
{
SelectMin(HT,i,min1,min2);
HT[min1].parent=i;
HT[min2].parent=i;
HT[i].lchild=min1;
HT[i].rchild=min2;
HT[i].weight=HT[min1].weight+HT[min2].weight;
cout<<min1<<""<<min2<<endl;
}
}
//***********************************
//构造哈夫曼编码
//***********************************
/*哈夫曼编码的定义*/
typedef struct
{
charch;
charbits[10];
}CodeNode;
typedef CodeNode * HuffmanCode;
/*哈夫曼编码的构造*/
void CreateHuffmanCode(HuffmanTree&HT,HuffmanCode &HC,int n)
{
inti;
intstart;
intc;
intp;
char*cd;
charq;
HC=newCodeNode[n];
cd=newchar[n];
cd[n-1]='/0';
for(i=0;i<n;i++)
{
cin>>q;
HC[i].ch=q;
start=n-1;
c=i;
while((p=HT[c].parent)>=0)
{
--start;
cd[start]=(HT[p].lchild==c)?'0':'1';
c=p;
}
strcpy(HC[i].bits,&cd[start]);
}
deletecd;
}
/*哈夫曼编码的输出*/
void OutputHuffmanCode(HuffmanCode&HC,int n)
{
inti;
for(i=0;i<n;i++)
{
cout<<HC[i].ch<<""<<HC[i].bits<<endl;
}
}
void main()
{
inti;
cout<<"输入字符个数:";
cin>>i;
HuffmanTreeHT;
HuffmanCodeHC;
CreateHaffmanTree(HT,i);
CreateHuffmanCode(HT,HC,i);
OutputHuffmanCode(HC,i);
}
1.首先要构造一棵哈夫曼树,哈夫曼树的结点结构包括权值,双亲,左右孩子;假如由n个字符来构造一棵哈夫曼树,则共有结点2n-1个;在构造前,先初始化,初始化操作是把双亲,左右孩子的下标值都赋为0;然后依次输入每个结点的权值
2.第二步是通过n-1次循环,每次先找输入的权值中最小的两个结点,把这两个结点的权值相加赋给一个新结点,,并且这个新结点的左孩子是权值最小的结点,右孩子是权值第二小的结点;鉴于上述找到的结点都是双亲为0的结点,为了下次能正确寻找到剩下结点中权值最小的两个结点,每次循环要把找的权值最小的两个结点的双亲赋值不为0(i).就这样通过n-1循环下、操作,创建了一棵哈夫曼树,其中,前n个结点是叶子(输入的字符结点)后n-1个是度为2的结点
3.编码的思想是逆序编码,从叶子结点出发,向上回溯,如果该结点是回溯到上一个结点的左孩子,则在记录编码的数组里存“0”,否则存“1”,注意是倒着存;直到遇到根结点(结点双亲为0),每一次循环编码到根结点,把编码存在编码表中,然后开始编码下一个字符(叶子)
4.译码的思想是循环读入一串哈夫曼序列,读到“0”从根结点的左孩子继续读,读到“1”从右孩子继续,如果读到一个结点的左孩子和右孩子是否都为0,如果是说明已经读到了一个叶子(字符),翻译一个字符成功,把该叶子结点代表的字符存在一个存储翻译字符的数组中,然后继续从根结点开始读,直到读完这串哈夫曼序列,遇到结束符便退出翻译循环