[数据结构]哈弗曼树

[数据结构]哈弗曼树

哈夫曼树应用实例——哈夫曼编码

关键:要设计长度不等的编码,则必须使任一字节的编码都不是另一字符的编码的前缀–前缀编码
译码过程
分解接收字符串,遇“0”向左,遇“1”向右,一旦达到叶子结点,则译出一个字符,反复由根出发,直到译码完成。
特点:每一码都不是另一码的前缀,绝不会译错。

哈弗曼树的构造

哈弗曼树:带权路径长度最小的树。

相关术语
路径:由一结点到另一结点间的分支所构成
路径长度:路径上的分支数目
带权路径长度:结点到根的路径长度与结点上权的乘积
树的带权路径长度:树中所有叶子结点的带权路径长度之和

哈弗曼树的构造过程
基本思想:使权大的结点靠近根。
操作要点:对权值的合并、删除与替换,总是合并当前值最小的两个。

哈夫曼编码的构造
基本思想:概率大的字符用短码,小的用长码,构造哈弗曼树。
构造过程
①根据给定的n个权值{W1,W2,W3,……Wn},构造n棵只有根结点的二叉树
②在森林中选取两棵根结点权值最小的树作左右子树,构造一棵新的二叉树,置新二叉树根结点权值为其左右子树根结点权值之和。
③在森林中删除这两棵树,同时将新得到的二叉树加入森林中。
④重复上述两步,直到只含一棵树为止,这棵树即哈弗曼树。

哈弗曼树构造算法的实现
typedef struct
{
  int weght;
  int parent,lch,rch;
 }*HuffmanTree;

Huffman树的建立
//算法5.8 建立Huffman树
void CreateHuffmanTree(HuffmanTree &HT,int n){
	HT = new HTNode[2*n];
	for (int i = 1; i <= n; i++)
		cin >> HT[i].weight;
	for (int i = 0; i < n * 2; i++)
		HT[i].parent = HT[i].lchild = HT[i].rchild = 0;
	for(int i = n+1 ; i < 2*n ; i ++){
		int res1;
		int res2;
		Select(HT,i-1,res1,res2);
		
		HT[i].weight = HT[res1].weight + HT[res2].weight;
		HT[i].lchild = res1;
		HT[i].rchild = res2;
		
		HT[res1].parent = i;
		HT[res2].parent = i;
	}
}
Huffman编码
//算法5.9 构造并输出Huffman编码
void CreateHuffmanCode(HuffmanTree &HT,HuffmanCode &HC,int n)
{
	HC = new char*[n+1];
	char *cd = new char[n]; 
	cd[n-1] = '\0';
	int start,c,f;
	for(int i=1;i<=n;i++)
	{
		start = n-1;
		c = i;
		f = HT[i].parent;
		while(f)
		{
			--start;
			if(HT[f].lchild == 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]);
	}
	for(int i=1;i<=n;i++)
	{
		cout << HC[i]<<endl; 
	}
}

哈夫曼编码的几点结论
● 哈夫曼编码是不等长编码
● 哈夫曼编码是前缀编码,即任一字符的编码都不是另一字符编码的前缀。
● 哈夫曼编码树中没有度为1的结点。若叶子结点的个数为n,则哈夫曼编码树的结点总数为2n-1
● 发送过程:根据由哈夫曼树得到的编码表送出字符数据。
● 接收过程:按左0、右1的规定,从根结点走到一个叶结点,完成一个字符的译码。反复此过程,直到接收数据结束。

应用
● 利用二叉树求解表达式的值

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帅帅帅帅鸭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值