代码会在之后给出,此处仅提供思路。
目录:1.哈夫曼树的建立
2.哈夫曼树的先序遍历求编码
3.根据字符串译码
编写一个哈夫曼编码译码程序。
按词频从小到大的顺序给出各个字符(不超过30个)的词频,根据词频构造哈夫曼树,给出每个字符的哈夫曼编码,并对给出的语句进行译码。
为确保构建的哈夫曼树唯一,本题做如下限定:
(1)选择根结点权值最小的两棵二叉树时,选取权值较小者作为左子树。
(2)若多棵二叉树根结点权值相等,按先后次序分左右,先出现的作为左子树,后出现的作为右子树。
生成哈夫曼编码时,哈夫曼树左分支标记为0,右分支标记为1。
输入格式:
第一行输入字符个数n;
第二行到第n行输入相应的字符及其词频(可以是整数,也PTA可以是小数);
最后一行输入需进行译码的串。
输出格式:
首先按树的先序顺序输出所有字符的编码,每个编码占一行;
最后一行输出需译码的原文,加上original:字样。
输出中均无空格
输入样例:
3
m1
n1
c2
10110
输出样例:
c:0
m:10
n:11
original:mnc
PTA中的一道题,哈夫曼树的定义就不再赘述,下面对该题进行分析。
emmm首先将数据传入,首先创建结构体数组,结构体定义如下:
typedef struct TNode* BinTree;
struct TNode{
double weight;/*结点权值*/
int str;/*判断是否为叶子结点*/
int flag;/*判断左右子树*/
int length;/*定义哈夫曼编码长度*/
BinTree Left;
BinTree Right;
};
,叶结点数为N,则哈夫曼树的结点总数为2*N-1,所以结构体数组的大小设置为2*N-1,对前 N 个 数组中的结构体中的weight 和str赋值即可。
该题涉及的操作有三步:哈夫曼树的建立、编码、译码。
1.哈夫曼树的建立:
因为原数组前N个数据已经有序,利用for循环,每次取前两个数据相加并将取出的两个数据作为左右子树生成新结点放入数组,然后对数组进行稳定排序(不改变数组原有次序)
(2)若多棵二叉树根结点权值相等,按先后次序分左右,先出现的作为左子树,后出现的作为右子树。
for(i=0;i<2*N-1;i+=2)
2.哈夫曼树的先序遍历求编码
利用堆栈来实现先序遍历的非递归算法,编码用数组存储。求编码有两种方法:
1.先求出每个结点的编码长度(这点利用递归可以轻松实现)。每个结点编码等于上个结点的编码加上此结点的flag值即可,由于我们已经算出各个结点的编码长度,此处可理解为在数组里,从编码长度-1的位置开始加入此结点的flag值(0或1).
2.在结构体中加入一个 指向父结点的指针,从叶节点开始向父结点进行遍历,可得到此结点的编码,循环即可求解。
3.根据字符串译码
字符串中每位数字代表着左子树或右子树,所以for循环取数向下深入即可得到对应字符。
写完觉得并不难,但当时写踩了很多坑,看了还不太明白的欢迎提问我哦。第一次写博客,叙述逻辑可能有些不太清晰,欢迎大家留言指正!