哈夫曼编码除了在编码上我们来寻找最优的不定长的前缀码的最小的码长,在文件归并上也有应用。现有一组长度不相同的已经排好序的文件,文件内部是排好序的,这些文件构成一个集合,把这些文件合并起来,合并成一个最大的文件,这个文件包含了所有文件,也就是这些所有的小文件,那么归并的时候,采用归并排序的方法相当于首先把它对应一个二叉树来进行操作,其实就和哈夫曼编码很像了,可以对集合中最小的两个做归并,归并完之后,再对小的两个做归并,这样操作完之后,归并之后比较的次数是最少的。
一、问题描述
问题:给定一组不同长度的排好序文件构成的集合S={f1,…,fn},其中fi表示第i个文件含有的项数。使用二分归并将这些文件归并成一个有序文件。
归并过程对应于二叉树:文件为树叶。fi与fi归并的文件是他们的父结点。
二、实例说明
实例:S={21,10,32,41,18,70}
1、两两顺序归并
(1)首先从集合里面挑选出两个最小的21的规模和10的规模,将它们两个做一个归并,归并完之后得到一个规模为31的文件
(2)接下来对32和41进行操作,得到一个规模为73的文件
(3)对31和73进行操作,得到一个规模为104的文件
(4)将18和70进行操作,得到一个规模为88的文件
(5)将104和88进行操作,得到一个规模为192的文件
①(21+10-1)+(32+41-1)+(18+70-1)+(31+73-1)+(104+88-1)=483
②(21+10+32+41)x3+(18+70)x2-5=483
代价计算公式 ∑ i ∈ s d ( i ) f i − ( n − 1 ) \sum\limits_{i \in s}^{}d(i)f_{i}-(n-1) i∈s∑d(i)fi−(n−1)
但是这样做的计算代价(将两个有序的文件合并成一个有序的文件的时候需要做的比较的次数),按照这样的顺序,相当于两个有序数组变成一个有序的数组比较的次数刚好是两个规模加起来减1,这样的操作方法归并代价是483
2、Huffman树归并
输入:S={21,10,32,41,18,70}
使用哈夫曼树构造归并的过程是这样的:
(1)挑出两个文件规模最小的10和18,合并得到一个规模为28的文件
(2)28,21,32,41,18,70是新的字符集,可以看做是新的文件,两个文件合并成一个大的文件
(3)剩下的文件又再次回到递归问题上,文件变少了,但所有的文件各自都是有序的
(4)这个时候又挑出两个较小的,以此类推哈夫曼树构造的过程
代价:(10+18)x4+21X3+(70+41+32)x2-5=456
按照这个树构造的过程来做有序文件的合并,它的次数比第一种方案要少,刚好和树的构造过程是一样的,最后的结果是456
排在越下面的文件它需要和别的文件进行合并,在合并的时候需要比较。就相当于哈夫曼编码的字符有些相同。从树的纵深角度来看,排在越下面,需要比较的次数就越多
,比如70规模的这个文件,它只需要两次就到达最大文件,只需要经过两轮比较,其实就相当于规模越小的,那就比较的次数多一点;规模越大的,那就比较的次数少一点。
所以有序文件的归并采用两两归并算法归并的次序就和哈夫曼编码的次序等同起来
三、总结
-
哈夫曼算法的正确性证明:
对规模归纳 -
哈夫曼算法的应用:
文件归并
哈夫曼算法的应用,虽然是两个问题但是发现它们具有相同的性质,为了达到最小的比较的次数和想要达到编码的最小的平均码长在问题的理解上有相似的地方。