哈夫曼实践报告
学号 20182329 2019-2020-1 哈夫曼实践报告
- 课程:《程序设计与数据结构》
- 班级: 1823
- 姓名: 李一卓
- 学号:20182329
- 实验教师:王志强
- 实验日期:2019 11月19日
- 必修/选修: 必修
1.实验内容
- 设有字符集:S={a,b,c,d,e,f,g,h,i,j,k,l,m,n.o.p.q,r,s,t,u,v,w,x,y,z}。
给定一个包含26个英文字母的文件,统计每个字符出现的概率,根据计算的概率构造一颗哈夫曼树。
并完成对英文文件的编码和解码。
要求:- 准备一个包含26个英文字母的英文文件(可以不包含标点符号等),统计各个字符的概率
- 构造哈夫曼树
- 对英文文件进行编码,输出一个编码后的文件
- 对编码文件进行解码,输出一个解码后的文件
2. 实验过程及结果
-
- 将所有带权值的结点按权值从小到大排列;
- 依次选取权值最小的结点放在树的底部,权值小的在左边(取出的结点相当于从这些结点的集合中剔除);
- 生成一个新节点作为这两个结点的父节点,且父节点的权值等于这两个结点权值之和,然后要把这个新结点放回我们需要构成树的结点中,继续进行排序;
重复上述2、3步骤,直至全部节点形成一棵树,此树便是哈夫曼树,最后生成的结点即为根节点。这样构成的哈夫曼树,所有的存储有信息的结点都在叶子结点上。
这是在书面上实现哈夫曼的过程
- 而在编程上实现哈夫曼首先先得实现节点,然后有基本的树。
将一个字符串中出现的字符生成其对应的哈夫曼编码
-
统计出现的字符及频率
-
将各个字符创建为叶子结点,频率为结点的权值,用链表保存这些叶子结点
-
将结点队列中的结点按权值升序排列
-
取出权值最小的两个结点构建父节点(要从链表中删除取出的结点),将新生成的父节点添加到结点链表,并从新排序
-
重复4步骤,直到只剩下一个结点
-
返回最后的结点,即为哈夫曼树的根节点。
- 这是主要的方法
public void creatHfmTree(String str) {
this.str = str;
NodeList = new LinkedList<HNode>();
charList = new LinkedList<CharData>();
// 1.统计字符串中字符以及字符的出现次数
// 以CharData类来统计出现的字符和个数
getCharNum(str);
// 2.根据第一步的结构,创建节点
creatNodes();
// 3.对节点权值升序排序
Sort(NodeList);
// 4.取出权值最小的两个节点,生成一个新的父节点
// 5.删除权值最小的两个节点,将父节点存放到列表中
creatTree();
// 6.重复第四五步,就是那个while循环
// 7.将最后的一个节点赋给根节点
root = NodeList.get(0);
}
3. 实验过程中遇到的问题和解决过程
-
问题:在编写测试代码的时候我吧文件读入,然后按照字符输出发现只是输出了路径的地址。
-
解决方法:我是直接把自己以前编写的读取字符型和数字的读取方法直接搬了过来,没有改正返回值,而且也没有用read写入。