二叉树:哈夫曼树

哈夫曼树

判断树:用于描述分类过程的二叉树

树的路径长度: 树根到每一个结点的路径长度之和。记作TL

权(weight): 将树中结点赋给一个有着某种含义的数值。

结点的带权路径长度:从根结点到该结点之间的路径长度与该结点权的乘积

树的带权路径长度: 树中叶子结点的带权路径长度之和。

构造哈夫曼树

1、构造森林全是根;2、选用两小造新树

3、删除两小添新人;4、重复2、3剩单根

构造算法实现

typedef struct HTNode{
    int weight;
    int parent,lch,rch;
} HTNode, *HuffmanTree;

例:有 n=8 ,权值为W = {7,19,2,6,32,3,21,10} 构造哈夫曼树

构造算法的思路 (结构数组):
在这里插入图片描述
在这里插入图片描述

代码实现

void CreateHuffmanTree(HuffmanTree& HT,int n){
	//构造哈夫曼树
	if(n<=1)  return;
	int m=2*n-1;
	HT=new HTNode[m+1]; //0单元号未用,下标从1开始 
	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++){
		cin >> HT[i].weight;  //输入前n个结点的权值 
	} 
// 初始化结束,下面创开始创建哈夫曼树

 for(int i=n+1;i<=m;i++){
 	/* 在select函数中,在前n个结点中通过n-1次的选择两个权值较小的结点,
	 进行合并,删除 来创建哈夫曼树 */
     
	 int s1=0,s2=0;
 	Select(HT,i-1,&s1,&s2);
 	/* 在 Parent == 0 中挑选出两个权值较小的结点,且s1<s2;
	 合并成一个新的结点,新的结点的结点号为i ,此时s1和s2结点的双亲结点即为i */
     
 	HT[s1].parent=i; 
    HT[s2].parent=i;
 	HT[i].lchild=s1;//将s1和s2分别作为结点i的左右孩子 
 	HT[i].rchild=s2;
 	HT[i].weight=HT[s1].weight+HT[s2].weight;//结点i的权值为左右孩子之和 
 } 
 
}

哈夫曼编码

编码方式
  1. 统计字符集中每个字符在电文中出现的平均频率(概率越大,要求编码越短)
  2. 利用哈夫曼树的特点:权越大的叶子离根越近;将每个字符的概率值作为权值,构造哈夫曼树。则概率越大的结点,路径越短。
  3. 在哈夫曼树的每个分支标上0或1:结点的左分支标0,右分支标1
  4. 把从根到每个叶子的路径上的标号连接起来,作为该叶子代表的字符的编码

例:

设组成电文的字符集D及其分布概率W为:

D={ A , B , C , D , E , F , G }

W={ 0.40 , 0.30 , 0.15 , 0.05 , 0.04 , 0.03 , 0.03 } 设计哈夫曼编码

在这里插入图片描述

A 0 ; B 11; C 01; D 10011; E 10010 ; F 10001

注:

1、哈夫曼编码保证是前缀编码:因为没有一片叶子是另一片叶子的祖先,所以每个叶节点的编码就不能使其他叶结点编码的前缀。

2、因为哈夫曼树的带权路径长度最短,故字符编码的总长最短。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值