最优前缀码

本文介绍了哈夫曼编码的概念,它是一种用于数据压缩的二元前缀码。通过贪心算法实现,确保了没有码字是其他码字的前缀,从而避免了编码歧义。哈夫曼算法通过不断合并频率最低的两个节点来构造最优二叉树,保证了平均码长最短。算法的时间复杂度为O(nlogn)。以字符集和频率为例展示了算法的实现过程和代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.背景

代码(码字):Q{001,00,010,01}表示字符a,b,c,d
同一序列:0100001
产生两种译码(产生歧义):01 00 001;010 00 01。
二元前缀码:任何字符的代码不能作为其他字符字符代码的前缀
利用二元前缀码译码:从第一个字符开始依次读入每个字符(0或1),如果发现读到的子串与某个码字相等,就将这个子串译作对应的码字;然后从下一个字符开始继续这个过程,知道读完输入的字符串为止。
二元前缀编码存储:二叉树结构,每个字符作为树叶,对应这个字符的前缀码看作根到这篇树叶的一条路径,每个节点通向左儿子的便记作0,通向右儿子的边记作1。
字符集合C={x1,x2,…,xn}
xi的频率是f(xi)
d(xi)表示字符xi二进制位数,也就是xi的码长
二元前缀编码:二叉树
码字:树叶
码字的二进制位数:树叶的深度
存储一个字符所使用的二进制数的平均值
在这里插入图片描述

最优二元前缀码:每个码字平均使用二进制位数最小的前缀码

2.问题

给定字符集C={x1,x2,…,xn}和每个字符的频率f(xi),求关于C的一个最优前缀码。

3.解析

构造最优前缀码的贪心算法就是哈夫曼算法(Huffman)
算法实现步骤:
1)初始化n个单节点的树,每个字符的概率记在树的根中,用作树的权重;
2)找到两棵权重最小的树,把它们作为新树中的左右子树,并把权重和记作新的权重记录在新树的根中;
3)重复第二步直到只剩一棵单独的树。
算法正确性证明:
在这里插入图片描述
证明:假设Huffman算法对于规模为k的字符集都得到最优前缀码,那么对于规模为k+1的字符集也得到最优前缀码.
n=2,字符集C={x1,x2},对任何代码的字符至少都需要1位二进制数字.Huffman算法得到的代码是0和1,是最优前缀码.
在这里插入图片描述
假设Huffman算法对于规模为k的字符集都得到最优前缀码,考虑规模为k+1的字符集C={x1,x2,…,xk+1},其中x1,x2∈C是频率最小的两个字符.令C’ = (C-{x1,x2})∪{z},f(z) = f(x1) + f(x2).
根据归纳假设,算法得到一棵关于字符集C’,频率f(z)和f(xi)(i=3,4,…,k+1)的最优前缀码的二叉树T’.
将x1,x2作为z的儿子附到T’上,得到树T,那么T是关于C = (C’-{z})∪{x1,x2}的最优前缀码的二叉树.
在这里插入图片描述
反证:如果T不是关于C的最优前缀码二叉树,则存在更优树T*,B(T*)<B(T),且由引理1,其树叶兄弟是x1和x2.去掉T中x1和x2,得到T’ .根据引理2,B(T*’) = B(T*) - (f(x1) + f(x2)) < B(T) - (f(x1) + f(x2)) = B(T’). 这与T’是一棵关于C’的最优前缀码的二叉树矛盾. 因此,T就是C的最优解。

算法实例:
{1,2,2,8,10,10,16,18}
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.设计

算法伪代码

算法 Huffman(C)
输入:C={x1,x2,...,xn},f(xi),i=1,2,...,n
输出:Q						//队列
n←|C|
Q←C							//频率递增队列Q
for  i←1 to n-1 do
	z←Allocate-Node()		//生成结点
	z.left←Q中最小元		//最小作z左儿子
	z.right←Q中最小元		//最小作z右儿子
	f(z)←f(x)+f(y)
	Insert(Q,z)				//将z插入Q
return Q

5.分析

算法时间复杂度
O(nlogn)频率排序;for 循环 O(n),插入操作 O(logn),算法时间复杂度是 O(nlogn) .

6.源码

算法源码地址
https://github.com/Ying917/Algorithm-Analysis/blob/master/Huffman.cpp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值