1.名词解释
- 路径与权
从起始节点到目标节点所经过的分支序列为路径,所经分支数目为路径长,若给节点赋值,则称此值为权。 - 节点的带权路径长
节点的带全路径唱等于该节点的权与根节点到该节点的路径长之积。 - 树的带权路径长(WPL)
树的带权路径长为所有叶子节点的带权路径长之和。 - 图示(今天带了数位板就直接用笔画了(懒))
2.Huffman树简介
给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。(百度百科)
3.Huffman树的构造
分为3步:
1)将每个节点视作一棵树,全部节点组成一个森林。
2)选取所有树中权值最小的两棵树,分别作为一个新节点的左子树与右子树,构成一棵新树,该树的权值为左右两棵子树权值之和。
3)重复步骤二直到仅剩一棵树,该树为所求Huffman树。
如图所示:
4.Huffman编码
比如说要传输一个由ABCDEF组成字符串,每个字母采用0与1编码,传统编码方式需要用到三位。假设要传输这样一个字符串:ABBBBCCDDDDDDDDEEEEEFFFFFFF,即六个字母出现次数分别为1、4、2、8、5、7时,按照传统编码方式需要传输81位。然而,并不是每个字母都要用到三位编码,而且传输位数越多成本越高。所以,需要用最少的位数传输这样的字符串,就要为每个字母重新编码。这种编码就叫做Huffman编码。
Huffman编码分为三部。首先按权值构造Huffman树,然后将该树所有节点与左孩子连接路径标0,与右孩子的标1,根到叶子节点的路径为叶子节点的Huffman编码。如图所示:(还是上面的例子)
对字符进行Huffman编码后,传输上述字符串仅用64位,明显少于传统编码的81位。
5.Huffman树及编码的实现
-
基本思路
首先将各个节点按权值置于优先队列中,数值越小优先级越高。然后开始进行树的构建,每次出队两个节点,将这连个节点与一个新节点构成新树入队,重复以上操作直到队列中只有一个树,该树位Huffman树。将该树出队后,进行BFS并依次记录遍历路径,向左遍历为0,向右遍历为1,将路径存入叶子节点,输出叶子节点与路径,即Huffman编码。 -
设计问题
处理一组数据,第一行为一个整数n,代表有n个数据需要处理,第二行到第n+1行每行两个数据,分别为一个字符与该字符在某个序列中出现次数。输出每个字符及其所对应的Huffman编码。 -
代码实现
#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#