引子
当操作的数目很大的时候,有时候只需要改变一下判断的顺序,可以减少执行时间,两种判别树的效率是不一样的。
哈夫曼树就是一种效率最高的判别树,也称之为最优二叉树。
一、哈夫曼树的基本概念
- 路径:从树中一个结点到另一个结点之间的分支构成这两个结点间的路径。
- 结点的路径长度:两个结点路径上的分支数。
- 数的路径长度:从树根到每一个节点的路径长度之和。记作:TL
- 结点数目相同的二叉树中,完全二叉树是路径长度最短的二叉树。
- 权:将树中结点赋给一个存有某种含义的数值,则这个数值称为该结点的权。
- 结点的带权路径长度:从根节点到该结点之间的路径长度与该结点的权的乘积。
- 树的带权路径长度:树中所有的叶子结点的带权路径长度之和。
例子:
哈夫曼树就是带权路径长度最短的树。
如何构造哈夫曼树?
构造方法如下:
具有相同带权结点的哈夫曼树不唯一。
例子一:
包含n棵树的森林要经过n-1次结合才能形成哈夫曼树,共产生n-1个新节点。所以包含n个叶子节点的哈夫曼树中共有2n-1个及结点。且哈夫曼树的节点的度数只有0或2,没有1.
例子二:
二、哈夫曼树的存储结构
- 采用顺序存储结构----一维结构数组
- 结点类型定义
存储结构如下所示:
typedef struct{
int weight; //权值
int parent,lch,rch; //双亲结点,左孩子结点,右孩子结点
}HTNode,*HuffmanTree;
构建哈夫曼树思路
例子:
哈夫曼树初始化与实现
伪代码如下,比较容易理解:
void CreateHuffmanTree(HuffmanTree HT,int n){
if(n <= 1) return;
m = 2*n-1; //数组共2n-1个元素
HT = new HTNode[m+1]; //HT[m]表示根节点
for(i = 1; i < m; i++){ //将2n-1个元素的lch,rch,parent置0
HT[i].lch = 0;
HT[i].rch = 0;
HT[i].parent = 0;
}
for(i = 1; i < m; i++){ //输入前n个元素的weight值
cin >> HT[i].weight;
}
for(i = n+1; i < m; i++){ //合并产生n-1个结点
Select(HT, i-1, s1,s2); //选择两个双亲为0且权值为最小的结点,返回在HT中的s1,s2序号
HT[s1].parent = i;HT[s2].parent = i; //从表中删除s1,s2
HT[i].lch = s1;HT[i]rlch = s2; //s1,s2分别作为i的左右孩子
HT[i].weight = HT[s1].weight + HT[s2].weight; //i的权值为左右孩子权值之和
}
}
三、哈夫曼编码
如何编码使得电文总长最短? -----哈夫曼编码
例子:如上编码就不会有歧义
特点:
- 哈夫曼编码能够保证是前缀编码,因为每一个结点路径都是不一样的;
- 哈夫曼树能保证字符编码总长度最短,因为本来哈夫曼树的带权路径长度最短。
四、哈夫曼编码算法实现
从底层反推到跟结点,判断是是左孩子还有孩子,然后标志01.
- cd[start]:用来不断的存储标志01
- HC[i]:用来存储结果
- HT[i]:哈夫曼树结构
代码实现:
void CreatHuffmanCode(HuffmanTree HT, HuffmanCode &HC, int n){
//从叶子到跟逆向求每个字符的哈夫曼编码,存储到编码表中
HC = new char* [n+1]; //分配n个字符编码的头指针矢量
cd = new char[n]; //分配临时存放编码的动态数组空间
cd[n-1] = '\0'; //编码结束符
for(i = 1; i <= n; i++)
{
start = n-1;
c = i;
f = HT[i].parent;
while( f != 0) //当还不是根节点时一直回溯
{
start--;
if(HT[f].lchild == c) //结点c是f的左孩子,则生成代码0
cd[start] = '0';
else //结点c是f的右孩子,则生成代码1
cd[start] = '1';
c = f; //以下两步是回溯的作用
f = HT[f].parent; //自己成为双亲再查找
}
HC[i] = new char[n - start];//为第i个字符串编码分配空间
strcpy(HC[i],&cd[start]); //将求得的编码从临时空间cd复制到HC的当前行中
}
delete cd; //释放临时空间
}
五、哈夫曼编码-文件的编码和解码
- 编码实现过程
- 解码实现过程
- 例子
参考链接:青岛大学–王老师授课视频