Huffman树(上)

目录

Huffuman树的概念和应用

概念

应用

哈夫曼树的构造算法

哈夫曼编码


Huffuman树的概念和应用

概念

在树中,

一个结点到达另一个结点之间的分支构成两个结点之间的路径,路径上的分支数目是路径长度。

从树的根节点到达每一个结点的路径长度之和叫做树的路径长度。

从树的根结点到某叶子结点之间的路径长度和该结点上权的乘积称为该结点的带权路径长度。

带权路径长度(WPL)最小的二叉树是哈夫曼树。

若要设计长短不同的编码,则必须是任意字符的编码不是另一个字符编码的前缀,这种编码称为前缀编码。

应用

1.在成绩不同区间时,用ifelse判断时,大部分成绩位于七十到九十之间,而if语句大多从60或者90开始判断,效率不高,哈夫曼树的构造有效对这一问题进行改进。但是哈夫曼树构造相对复杂,主要目的不在于转换成绩。

2.在当时,哈夫曼树主要用于解决远距离通信的数据传输的优化问题,也可以理解为压缩和解压缩。规定左分支代表0右分支代表1,则从根结点到叶子结点所经过的路径分支组成的0和1的序列便为该结点对应字符的编码,这就是哈夫曼编码。

哈夫曼树的构造算法

哈夫曼树其实是属于贪心算法。也就是在问题求解时,总是做出当前看来最好的选择,也就是说,不从整体最优加以考虑,而只是得到某种意义的局部最优解,但是此时的局部最优解恰好等于全局最优解。

哈夫曼树的构造算法也就是找到每次权值最小的子树构造新的二叉树,且该二叉树的结点为其左右结点根的权值之和。

typedef struct {
	char data;//结点值
	double weight;//权值

	int parent;
	int lchild;
	int rchild;
} HmTNode;

//n个叶子结点,2*n-1个结点
void CreatHmT(HmTNode hm[], int n) {
	//先将所有结点的初始值设置为-1
	for (int i = 0; i < 2 * n - 1; i++)
		hm[i].parent = hm[i].lchild = hm[i].rchild = -1;

	int min1, min2; //存储局部最优解
	int lnode, rlode; //存储左右结点
	//哈夫曼树的0~n-1存的是叶子结点,从第n个开始构造
	for (int i = n; i < 2 * n - 1; i++) {
		min1 = 32767, min2 = 32767;
		lnode = -1, rlode = -1;
		//在前n个未构造的数值中寻找最小的两个构造
		for (int k = 0; k < n; k++) {
			if (hm[k].parent == -1) {
				if (hm[k].weight < min1) {
					min2 = min1;//保存上一个最小的信息
					rlode = lnode;

					min1 = hm[k].weight;//保留这次最小的信息
					lnode = k;
				} else if (hm[k].weight < min2) {
					min2 = hm[k].weight;
					rlode = k;
				}
			}
		}
		//找到两个最小的结点之后,构造子树
		hm[i].weight = hm[lnode].weight + hm[rlode].weight;
		hm[i].lchild = lnode, hm[i].rchild = rlode;
		hm[lnode].parent = i, hm[rlode].parent = i;
	}
}

哈夫曼编码

哈夫曼编码的实质是使用频率越高的字符采用更简短的编码。

//哈夫曼编码
const int N = 1010;

typedef struct {
	char cd[N];//存放当前结点的哈夫曼编码
	int start;//
} HCode;

void CreateHCode(HmTNode hm[], HCode hcd[], int n) {
	//根据哈夫曼树求哈夫曼编码
	HCode hc;
	int c, f;
	for (int i = 0; i < n; i++) {
		hc.start = n;
		c = i;
		f = hm[i].parent;
		//code
		while (f != -1) { //左子树0右子树1
			if (hm[f].lchild == c)
				hc.cd[hc.start--] = '0';
			else
				hc.cd[hc.start--] = '1';
			c = f;
			f = hm[f].parent; //继续循环
		}
		hc.start++;
		hcd[i] = hc; //从start开始到n结束
	}
}

参考资料:

《大话数据结构》程杰

《数据结构教程》李春葆

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Daxiuy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值