输出样例 1
a:7 b:5 c:2 d:4
1 7 7 0 0
2 5 6 0 0
3 2 5 0 0
4 4 5 0 0
5 6 6 3 4
6 11 7 2 5
7 18 0 1 6
a:0 b:10 c:110 d:111
00000001010101010110110111111111111
aaaaaaabbbbbccdddd
a:2 b:1 c:3
1 2 4 0 0
2 1 4 0 0
3 3 5 0 0
4 3 5 2 1
5 6 0 3 4
a:11 b:10 c:0
111110000
aabccc
思路:
比较详细了。。希望你看过后可以先自己动手尝试实现~
哈夫曼树的节点说明一下:一个节点存的除了左右节点,parent,权值、还包括字符和它的编码。
看第一行输出,是每个字母及其出现频率,那么可以想到用map来存储相关信息,字母是key,出现次数通过遍历字符串累加作为value。
之后是创建树,先让题目里给的那几个节点初始化,双亲和子节点都是0,利用刚才的map的迭代器,存每个结点的data和weight。ass是辅助map,用来记录当前权值(key)和是否已经被使用过了(value,0表示用过了,1表示没有,一会创建新节点的权值要从这里面挑选value里是1且最小的返回key),故ass[it->second]=1.
FindParent返回的是一个嵌套的对组。设置最小权值min1,min2以及其对应的节点序号i,j,先遍历ass,依据上述选择标准选出min1。min2不能与min1相同——若不存在相同的权值,则min1!=min2;若存在相同的权值,那么min2不会被赋值,仍然是30000(一开始设个比较大的初始值),这种情况下再修改min2=min1。在哈夫曼树里遍历min1,min2,记录其对应的节点序号,此时又要考虑min1=min2的情况,若发生了,那么再单独遍历一次树,设一个flag记录第二次出现树里某个节点权值=min2的时候再赋值j=节点序号。返回一个包含两个最小权值和孩子序号的对组。
回到Create函数里,用上述返回值创建新节点,新权值是两个老权值相加,子节点序号也有了,顺便更新子节点的parent是现在节点的序号。最后别忘了令最后一次构造的节点parent=0!!
接下来是为每个节点创建哈夫曼编码,从每个叶子节点开始向上求parent,再看它是parent的左节点还是右节点,判断code是加一个0还是加一个1.注意:代码中code每次赋值不能写+=,不然顺序是反着的!!
接下来就到了轻松愉快的输出环节~第一行map m解决;表格和code就遍历树输出即可;解码如果想省事的话就直接输出原字符串xd,如果想写的话就在输出编码的时候用string decode记录下编码后的字符串,解码输出即可;
解码函数思路如下:在树里从头遍历编码字符串的每一位,是0就走左边,是1就走右边,直到到了叶子节点,输出那个节点的data即可,别忘了每次输出完了之后回到根节点呀!!
代码如下:
#include
#include
#include
#include
#include
#include