目录
哈夫曼树的基本概念
(1)路径:从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径。
(2)路径长度:路径上的分支数目称作路径长度。
(3)树的路径长度:从树根到每个结点的路径长度之和。
(5)结点的带权路径长度:从该结点到树根之间的路径长度与结点上权的乘积。
(6)树的带权路径长度:树中所有叶子结点的带权路径长度之和,通常记为WPL
(7)哈夫曼树:带权路径长度WPL最小的二叉树。(又称为最优二叉树)
哈夫曼树的结点结构和存储表示
typedef struct {
int weight; //结点的权值
int parent,lchild,rchild; //结点的双亲、左孩子、右孩子
}HTNode,*HuffmanTree;
相关代码
1.构造哈夫曼树
void CreateHuffmanTree(HuffmanTree &HT,int n)
{
if(n<=1) return;
m=2*n-1;
HT=new HTNode[m+1]; //0号单元未用,所以需要动态分配m+1个单元,HT[m]表示根结点
for(int i=1;i<=m;++i) //将1-m号单元的双亲、左孩子、右孩子的下标都初始化为0
{
HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;
}
for(int i=1;i<=n;++i) //输入前n个叶子权值
{
cin>>HT[i].weight;
}
/*----------初始化工作结束,开始创建哈夫曼树----------*/
for(int i=n+1;i<=m;++i)
{
Select(HT,i-1,s1,s2); //在HT[k](1<=k<=i-1)中选择两个其双亲域为0且权值最小的结点,并返回他们在HT中的序号s1和s1
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;
}
}
哈夫曼树编码
- 约定左分支标记为0,右分支标记为1
- 前缀编码(任一个编码都不是其他任何编码的前缀)、哈夫曼编码。
- 哈夫曼编码性质:
1)哈夫曼编码是前缀编码。
2)哈夫曼编码是最优前缀编码。
- 算法实现
- 编码:叶子-->根(做题的时候:根-->叶子)
- 译码:根-->叶子(做题的时候:叶子-->根)