定义:
- 路径: 树中一个结点到另一个结点之间的分支构成这两个结点之间的路径。
- 路径长度:路径上的分枝数目称作路径长度。
- 树的路径长度:从树根到每一个结点的路径长度之和。
- 结点的带权路径长度:在一棵树中,如果其结点上附带有一个权值,通常把该结点的路径长度与该结点上的权值之积称为该结点的带权路径长度(weighted path length)
构造方法:
霍夫曼树编码解码:
#include<iostream>
#include<string>
using namespace std;
typedef struct HTNode
{
char c;
double weight;
int parent;
int lchild;
int rchild;
};
void creatHFMTree(HTNode* ht,int n)
{
int lchild,rchild;
double wl,wr;
for(int i=0;i<2*n-1;i++)
ht[i].parent=ht[i].lchild=ht[i].rchild=-1;
for(int i=n;i<2*n-1;i++)
{
wl=wr=DBL_MAX;
lchild=rchild=-1;
for(int j=0;j<i;j++)
{
if(ht[j].parent==-1)
{
if(ht[j].weight<wl)
{
wr=wl;
wl=ht[j].weight;
rchild=lchild;
lchild=j;
}
else if(ht[j].weight<wr)
{
wr=ht[j].weight;
rchild=j;
}
}
}
ht[lchild].parent=ht[rchild].parent=i;
ht[i].weight=wl+wr;
ht[i].lchild=lchild;
ht[i].rchild=rchild;
}
}
typedef struct HTCode
{
char* code;
int start;
};
void creatHFMCode(HTNode* hn,HTCode* hc,int n)
{
int f,tmp;
for(int i=0;i<n;i++)
{
hc[i].start=n;
tmp=i;
while((f=hn[tmp].parent)!=-1)
{
if(hn[f].lchild==tmp)
hc[i].code[hc[i].start--]='0';
else
hc[i].code[hc[i].start--]='1';
tmp=f;
}
hc[i].start++;
}
}
void printCode(HTCode* hc,HTNode* hn ,int n)
{
for(int i=0;i<n;i++)
{
cout<<hn[i].c<<":";
for(int j=hc[i].start;j<=n;j++)
cout<<hc[i].code[j];
cout<<endl;
}
}
void decoding(string s,HTNode* nodes,int num)
{
int root=num-1;
int tmpNode=root;
for(int i=0;i<s.size();i++)
{
if(s[i]=='0')
tmpNode=nodes[tmpNode].lchild;
else if(s[i]=='1')
tmpNode=nodes[tmpNode].rchild;
else
{
cout<<"error input"<<endl;
return;
}
if(nodes[tmpNode].lchild==-1)
{
cout<<nodes[tmpNode].c;
tmpNode=root;
}
}
cout<<endl;
}
int main()
{
int num=10;
HTNode* nodes=new HTNode[2*num-1];
for(int i=0;i<num;i++)
{
nodes[i].c=i+'a';
nodes[i].weight=i+2;
}
creatHFMTree(nodes,num);
HTCode* codes=new HTCode[num];
for(int i=0;i<num;i++)
codes[i].code=new char;
creatHFMCode(nodes,codes,num);
printCode(codes,nodes,num);
string s="000000011010";
decoding(s,nodes,2*num-1);
delete[] nodes;
delete[] codes;
return 0;
}