C++实现树 - 06 哈夫曼树编码

本文介绍了哈夫曼树的概念、路径长度、带权路径长度及其在数据压缩和通信编码中的应用。详细讲解了哈夫曼树的构造过程,通过C++代码展示了如何构建哈夫曼树及生成哈夫曼编码。最后,提供了从叶子结点到根的哈弗曼编码求解方法。

数据结构与算法专栏 —— C++实现

写在前面:
这一讲我们来学习一个比较有趣的树 —— 哈夫曼树,在许多非常知名的算法里也出现了哈夫曼树,这一讲我们就好好来唠唠什么是哈夫曼树。

前置概念

概念一:什么是结点路径的长度

从根结点到该结点的路径上的连接数。
在这里插入图片描述
例如上图(下面将会用到),从结点 28 到结点 2 的连接数为 3 。

概念二:什么是树的路径长度

就是树的每个叶子结点的路径长度之和,上图的树的路径长度就为 3 + 3 + 3 + 3 + 1 = 13 。

概念三:什么是结点的带权路径长度

结点的路径长度与结点权值的乘积。

概念四:什么是树的带权路径长度 WPL

就是树的所有叶子结点的带权路径长度之和。

应用场景

在数据膨胀、信息爆炸的今天,数据压缩的意义不言而喻。谈到数据压缩,就不能不提赫夫曼(Huffman)编码,赫夫曼编码是首个实用的压缩编码方案,即使在今天的许多知名压缩算法里,依然可以见到赫夫曼编码的影子。

另外,在数据通信中,用二进制给每个字符进行编码时不得不面对的⼀个问题是如何使电稳总长最短且不产生二义性。根据字符出现频率,利用赫夫曼编码可以构造出一种不等长的二进制,使编码后的电文长度最短,且保证不产生二义性。

当有了以上概念以后,我们就可以用WPL去判断一颗二叉树的性能。WPL的值越小,二叉树的性能越优。

哈夫曼树的构造

(1)给出我们要构造的结点权值。
在这里插入图片描述
(2)找出两个最小的权值,创建双亲结点,并且其权值等于这两个最小的权值结点之和。将这两个结点移出后续的大小判断,并将新创建的结点加入后续的大小判断。
在这里插入图片描述
(3)不断地重复上述操作。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//找到两个最小的权值(这里为了方便大家理解,就分开找两个最小值了)
void select(HuffmanTree huffmanTree[], int n, int &s1, int &s2) {
   
   
	int min;
	//遍历全部的结点,找出一个单结点
	for (int i = 1; i <= n; i++) {
   
   
		if (huffmanTree[i].parent == 0) {
   
   
			min = i;
			break;
		}
	}
	//继续遍历全部结点,找出权值最小的单结点
	for (int i = 1; i <= n; i++) {
   
   
		if (huffmanTree[i].parent == 0) {
   
   
			if (huffmanTree[i].weight < huffmanTree[min].weight) {
   
   
				min = i;
			}
		}
	}
	s1 = min;
	//进行和上面相同的操作,找到第二小的结点
	for (int i = 1; i <= n; i++) {
   
   
		if (huffmanTree[i].parent == 0 && i != s1) {
   
   
			min = i;
			break;
		}
	}
	for (int i = 1; i <= n; i++) {
   
   
		if (huffmanTree[i].parent == 0 && i != s1) {
   
   
			if (huffmanTree[i].weight < huffmanTree[min].weight) {
   
   
				min = i;
			}
		}
	}
	s2 = min;
}

//构建哈夫曼树
void 
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值