二叉树的应用举例
一 Huffman树及其构造算法
Huffman树又被称为H树
一 路径及长度
从树中的一个节点到另一个节点存在一条通路时,称这两节点之间存在一条路径。路径的分支树数(弧的数量)称为路径的长度。
除根节点之外每个节点只有一个直接前驱,所以说根节点到每个节点有且只有一条路径。
二树的路径长度
树的路径长度为根节点到任意节点的路径的长度之和,很显然对于有n个节点的二叉树来说,完全二叉树的路径长度最短。
三 加权节点
权是给每一个节点赋一个值,称此时的节点为加权节点,如A节点的权值为5,加权节点的长度为根节点到该节点的长度*该点的权值
四 树的加权路径长度WPL(Weighted Path Length)
树的加权路径长度为树中所有节点的加权路径长度之和
在确定的几个节点的任意组合中,其中加权长度最短的树为Huffman树
下面是构造Huffman树的方法
设定权集W={w1,w2.....wn}
1 初始化,构成n棵单节点的二叉树森林F={T1,T2,T3,T4,,,,,Tn},其中Ti为单节点且权值wi的二叉树。
2 从当前F中选择权值最小的两个节点,作为左右子树,构成一棵新的二叉树。新二叉树的权值为原本二叉树的权值之和。
3 从F中删除选中的那两个节点,并把新节点插入F中
4重复上述2,3直到只含有一课二叉树为止。
注意两次选出的子树谁作为左子树谁作为右子树没有区别。所以说H树不唯一。
设H树的叶节点个数为n(定权集中元素的个数),因为H树中出度为一的节点的个数为0,出度为2的节点个数为n-1,说以说树中总节点的个数为m=2n-1,所以说可以将节点储存在一维数组当中
算法实现
#include <stdio.h>
#include <stdlib.h>
#define n 8
#define m 2*n-1
typedef struct Node
{
int wi; //权值
char data; //存储的数据
int Parent; //父节点的存储位置
int LChild, RChild; //左右子节点的存储位置
}Huffman;
void CreateHuffman(Huffman HF[]) //节点个数
{
int i, j;
char w;
int a, b, temp;
int p, q;
int count;
for (i = 0; i<m; i++) //初始化
{
HF[i].wi = 0;
HF[i].Parent = 0;
HF[i].LChild = HF[i].RChild = 0;
}
for (i = 0; i<n; i++) //输入权值
{
scanf("%d", &w);
HF[i].wi = w;
}
a = 1000; //给a赋一个初始值
for (i = n; i<m; i++) //在添加m-n个新节点
{
for (j = 0; j<i; j++) //对已经添加的节点进行遍历
{
if (HF[j].Parent != 0) //还没有遍历过得节点
{
temp = HF[j].wi;
if (temp<a || temp<b)
{
q = p;
p = j;
b = a;
a = temp;
}
}
}
HF[i].wi = a;
HF[i].LChild = m;
HF[i].RChild = n;
HF[m].Parent = i;
HF[n].Parent = i;
}
}
二 Huffman编码及其构造
在信息传递中,会将数字或者字符转换为二进制代码进行表示,比如说A,B,C,D这四个字符可能会用00,01,10,11进行表示,为了减轻线路的压力要是编码的字节数尽可能的小,可以使用0,00,1,01来表示a,b,c,d但是这种表示方式可能会造成译码错误,所以说这种方式不可行,这样的编码方式被称为非前缀编码,非前缀编码可能会造成译码错误,前缀编码是任何一个编码都不是另一个编码的前缀。这样就不会造成译码错误。
使电文数量最小就要使用Huffman编码的知识,
在信息中编码的平均码长为:每个字符的码长*权值 之和,这相当与WPL,因此可以构造一棵Huffman树来找到最小编码方式。
例如有8个字母a,b,c,d,e,f,g,h这8个字母的权值为(w1,w2,w3,w4,w5,w6,w7,w8)使用这些信息构造一棵Huffman树,然后约定向左为0,向右为1这样就可以表示出所有的字符,并且平均字符长度最小。
但是Huffman的缺点是编码的长度是不确定的这样的话就会造成信息的传递不太方便。
浙公网安备 33010602011771号