最小堆实现哈夫曼树的构造及哈夫曼编码、解码

      以下程序的算法思想主要来自于浙江大学陈越老师主编的数据结构一书。最大堆(最小堆思想差不多)这里就不再多说,这里主要讲讲哈夫曼树的定义及实现。

Huffman Tree

相关概念:

结点的路径长度:从根结点到该结点的路径上分支的数目。

树的路径长度:树中每个结点的路径长度之和。(从树根到其余各结点的路径长度之和)

结点的带权路径长度(WPL):结点的路径长度与该结点所带权值的乘积。

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

      设一棵树有n个叶子结点,每个叶结点带有权值wk,结点的路径长度为lk,则树的带权路径长度可以表示为:

哈夫曼树的定义: 假设有n个权值,构造有n个叶子结点的二叉树,每个叶子结点的权值是n个权值之一,这样的二叉树可以构造很多棵,其中必有一棵是带权路径长度最小的,这棵二叉树就称为最优二叉树或哈夫曼树。

构造Huffman树的步骤:

(1)  根据给定的n个权值,构造n棵只有一个根结点的二叉树,n个权值分别是这些二叉树根结点的权;

(2) 设F是由这n棵二叉树构成的集合,在F中选取两棵根结点权值最小的树作为左、右子树,构造成一颗新的二叉树,置新二叉树根结点的权值等于左、右子树根结点的权值之和。为了使得到的哈夫曼树的结构唯一,规定根结点权值最小的作为新二叉树的左子树;

(3) 从F中删除(2)中作为左、右子树的两棵二叉树,并将新构造的二叉树加入到集合F中;

(4) 重复(2)、(3)步,直到F中只含一棵二叉树为止,这棵二叉树便是要建立的哈夫曼树。

说明:n个结点需要进行n-1次合并,每次合并都产生一个新的结点,最终的Huffman树共有2n-1个结点。

      为了便于抽取最小权值的子树,在树的构造过程中使用了最小堆及其插入,删除等操作。这里堆中的元素是一个加了权值的树结点的指针。

 

      说了这么多,也该实现代码了。100好几十行的代码撸下来,感觉自己神清气爽,等等...,编译没毛病,运行。。。呃呃呃,什么!!!我就输入了一个整数(表示接下来我要输入多少个权值),程序就跟我说拜拜了!!!于是我就只能进入搬砖工Debug模式了。。。调试程序嘛,当然要一步步来,首先当然是调试主程序里的第一个函数(CreateMinHeap(2*N)),我就在这个函数前后写了一句printf("ok\n"),一运行,,,O no,只有一个ok,当然这个函数有毛病,于是我进去这个函数定义里面一看,这老哥没毛病啊,左看右看,找不出来。。。想了老久,只好启动码农搬救兵(大佬-杰)模式,什么!!!你也看不出来???苍天啊,我的内心其实还有点【小窃喜】,救兵也没看出来,说明我这个问题不是一般的问题,我自己没看出来也还ok。我的肚子这时候又出来加速我的放弃了,于是我就打算吃饭,打道回府。。。

 

 

      故事到这里难道就结束了吗?no no no。在去食堂的路上,我想着作为一名党神圣的搬砖工,不能就这么放弃了啊,不然将来怎么建设党的伟大事业。我就在路上想啊想啊,越想越得劲,感觉思路越来越清晰,到了食堂打完饭一坐下,没吃几口饭,猛一拍大腿【卧槽】,想出来了。。。当时恨不得当场把电脑掏出来调试一波【别人会不会把我当傻子。。。】。主要问题是我在动态申请一个指针数组的时候给这个指针数组分配的内存空间(这时候指针数组的元素可能是空指针,或者不知道指向一个什么地方),我却在后面直接使用了这个指针指向的对象(结构体)里面的元素,这样肯定不行啊!!!比如说你指向了一片虚无的空间或者是指向一个不知道是什么地方,然后对另一个人说,这个地方有好多妹子,快去撩妹吧,撩你个大头鬼哦,你个糟老头子坏得很~,没给我地址怎么找这个地方!!!你要是指着女生宿舍说这个还差不多(不过咱们也不能真进去女生宿舍啊,进去了也别说是我教唆的【哈哈】)。于是我只好先一个个申请一个地址空间,再把他们赋值给这个指针数组就行了。(这里告诉我们一个道理,当你调不出代码的时候,出去吃个饭,或者散散步说不定就想出来了,大脑持续高负荷工作也是会累的)

      修改好之后运行程序没毛病,再也不会没执行完就崩溃了,说明程序大体上没什么毛病(诸如溢出、指针指向不明),只不过算法上的实现是需要程序员自己检查的。

      你们以为这就结束了吗?那你们也太小看程序员为什么高薪了(那是因为他们总写出满带bug的程序,然后他们成天到晚Debug,累得不行【过头了,过头了】),然后有人问,那直接写出没bug的程序呗,说的轻巧,大可一试,小程序倒还好,那种成百上千行的代码难道能完全没问题吗?哈哈,偏题了,偏题了。接下来这个问题是我也不曾想过会出现的,当然因为程序运行结果不对,我只好对写的函数一个个在主函数里面进行分别实现,当然,你很容易看出没问题的函数就没必要了。最后,终于定位在了哈夫曼构造函数这个函数里面(因为其他函数都没问题),但我非常不解啊,因为这个函数是教科书上有的,我原封不动

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值