-
路径:从树中一个结点到另一个结点之间的分支构成这两个结点间的路径
-
结点的路径长度:两结点间路径上的分支数。
-
树的路径长度:从树根到每一个结点的路径长度之和。记作TL
-
结点树目相同的二叉树中,完全二叉树是路径长度最短的二叉树
-
权(weight):将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权
-
1结点的带权路径长度:从根结点到该结点之间的路径长度与该结点的权的乘积
-
树的带权路径长度:树中所有叶子节点的带权路径长度之和。
哈夫曼树:最优树 带权路径长度最短的树
满二叉树不一定是最优二叉树
-
哈夫曼树中权越大的叶子离根越近
-
具有相同带权结点的哈夫曼树不唯一
2、哈夫曼树的构造算法 2.1 哈夫曼算法
-
构造森林全是根
-
选用两小造新树
-
删除两小添新人
-
重复 2、3 剩单根
包含n棵树的森林要经过n-1次合并才能形成哈夫曼树,共产生n-1个新结点
包含n个叶子节点的哈夫曼树中共有2n-1个结点
总结:
-
在哈夫曼算法中,初始时有n棵二叉树,要经过n-1次合并最终形成哈夫曼树。
-
经过n-1此=次合并产生n-1个新结点,且这 n-1 个新结点都是具有两个孩子的分支结点
-
哈夫曼树中共有n+n-1 = 2n-1 个结点,且所有的分支结点的度都不为 1。
采用顺序存储结构--- 一维结构数组
// 结点类型定义
typedef struct{
int weight;
int parent,lch,rch;
}HTNode,*HuffmanTree;
// 找出森林中权值最小的两个
void Select(HuffmanTree HT,int n,int &s1,int &s2) {
int minum;
int i;
for(i=1;i<=n;i++){
if(HT[i].parent == 0){
minum = i;
break;
}
}
for(i = 1;i<=n;i++){
if(HT[i].parent == 0){
if(HT[i].weight
3、哈夫曼编码
3.1 哈夫曼编码
-
统计字符集中每个字符在电文中出现的平均概率(概率越大,要求编码越短)
-
利用哈夫曼树的特点:权越大的叶子离根越近,将每个字符的概率值作为权重,构建哈夫曼树。则概率越大的结点,路径越短
-
在哈夫曼树的每个分支上标上0或1:
-
结点的左分支标0,右分支标1
-
把从根到每个叶子的路径上的标号连接起来,作为该叶子代表的字符的编码。
# include
# include
//存放哈夫曼编码
typedef char** HuffmanCode;
// 结点类型定义
typedef struct{
int weight;
int parent,lch,rch;
}HTNode,*HuffmanTree;
// 哈夫曼编码
void CreatHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n){
HC = new char*[n+1];
char *cd = new char[n];
cd[n-1] = ' ';
int start,c,f,i;
for(i=1;i<=n;i++){
start = n-1;
c = i;
f = HT[i].parent;
while(f!=0){
start--;
if(HT[f].lch == c){
cd[start] = '0';
}else{
cd[start] = '1';
}
c = f;
f = HT[f].parent;
}
HC[i] = new char[n-start];
strcpy(HC[i],&cd[start]);
}
delete cd; // 释放临时空间
}
3.2 文件的编码和解码



