探讨最优前缀码问题

首先看一下平均传输位数,定义如下:设定好的每一个码字给一个频率f(x),每一个频率乘码字的长度,频率指英文中26个字母在传输的文章中每个字母出现的次数,出现的越多在编码的时候用更短的编码,长度乘频率求平均值。平均值在不同设计的情况下有不同,不同方式下产生不同的前缀码,不同的前缀码对应着不同的平均传输位数,现在想要所有的设计中产生一种设计来,想要最小的平均传输位数,也就是所要求的最优的前缀码,这个时候的优化问题就是哈夫曼编码。对哈夫曼的操作肯定十分清楚,给一堆的频率,然后来设计哈夫曼编码,做题大家都会,如何证明哈夫曼树就是最优的方案呢?

一、问题描述

给定字符集C={x1,x2,……,xn}和每个字符的频率f(xi),i=1,2,……,n。求关于C的最优前缀码(平均传输位数最小)

二、实例演示

输入 a:45;b:13;c:12;d:16;e:9;f:5

编码:
f——0000
e——0001
d——001
c——010
b——011
a——1
Huffman-001

1、哈夫曼编码的过程

(1)从 (45,13,12,16,9,5)中挑出最小的两个来,5和9
(2)把5和9加起来,做成一个新的结点14,现在序列为(45,13,12,16,14)
(3)从(45,13,12,16,14)中挑出最小的两个来,13和12
(4)把13和12加起来,做成一个新的结点25,现在序列为(45,25,16,14)
(5)从(45,25,16,14)中挑出最小的两个来,16和14
(6)把16和14加起来合并成30(新的结点30),现在序列为(45,25,30)
(7)从(45,25,30)中挑出最小的两个来,25和30
(8)把25和30加起来,做成一个新的结点55,现在序列为(45,55)
(9)把45和55排成一排,合并成1个数做成结点,树构造完毕

2、写编码,左边为0右边为1

Huffman-002

3、平均位数

4x(0.05+0.09)+3x(0.16+.012+0.13)+1x0.45=2.24

三、代码实现

1、哈夫曼编码的过程实际上是哈夫曼算法的过程,哈夫曼树和算法构造的过程可以认为是构造树的时候是有一个算法的,其实就是这个挑出来合并再选择的过程

2、哈夫曼树算法伪码

算法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
	z.left←Q中最小元 //最小作z左儿子
	z.right←Q中最小元 //最小作z右儿子
	f(z)f(x)+f(y)
	Insert(Q,z) //将z插入Q
return Q

那么哈夫曼算法所得到的编码是不是最优的二元前缀码呢?这个问题是要去证明的,数据结构是不回去证明这个过程的,但是算法设计分析就是要层层递进,理解这个过程

四、证明过程

1、最优前缀码性质:引理1

字符集、频率给出后,存在最优的二元前缀码,二元前缀码的特点:字符的频率最小的两个码字x,y,他们一定是在兄弟的位置上,等长并且只有最后一位不同,一定是兄弟叶结点。给定任意一颗二元前缀码的树,一个编码就对应着一棵树。这里不考虑兄弟可以交换的情况。如果说最小频率的两个码字不在最下层的叶子结点,可以交换到下面并且换到下面的时候,是会让平均码长降低的。

引理1:C是字符集,∀ f(c) ∈C,f(c)为频率,x,y∈C,f(x),f(y)频率最小,那么最优二元前缀码使得x,y码字等长且仅在最后一位不同

f(x)≤f(a)
f(y)≥f(b)
tree-001
加入x和y的频率是很低的或者是最低的,把x换下去,和a交换;把y换下去,和b交换。那么这棵树就发生了两个对换,其实是会让平均码长降低的,证明十分简单,计算平均码长=每一个码字*频率累计起来 / 总个数,交换的时候,直观地理解x的频率本来是低的,a的频率比x要大,那么这两个交换,把频率大的变短,把频率小的变长,那这两者都有好处。h表示码长,f表示频率
tree-002
f(x)频率是最小的,f(a)频率要大一点,把码字的频率大的放上去,所以h缩小一点(h↓);频率特别小的h虽然增加(h↑),但是f(x)减小了( f(x)↓ ),那么这两者一增一减,因为其他地方没有变化,经过计算把小的往下面调整之后就可以让这个数变小,只有这两者发生变化

猜你喜欢

转载自blog.csdn.net/Prototype___/article/details/124510165