哈夫曼编码测试

任务详情

  • 设有字符集: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个英文字母的文件,统计每个字符出现的概率,根据计算的概率构造一颗哈夫曼树。
  • 并完成对英文文件的编码和解码。
    • 要求:
    • (1)准备一个包含26个英文字母的英文文件(可以不包含标点符号等),统计各个字符的概率
    • (2)构造哈夫曼树
    • (3)对英文文件进行编码,输出一个编码后的文件
    • (4)对编码文件进行解码,输出一个解码后的文件
    • (5)撰写博客记录实验的设计和实现过程,并将源代码传到码云
    • (6)把实验结果截图上传到云班课

任务分析与分析思路

  1. 首先要把字符集从文件中读出来,并保存在一个数组里面。这一步暂时想用IO流来实现。
  2. 紧接着是去计算每一个字符出现的频率。初步想用嵌套循环来实现,并把出现的概率存在另一个数组中。
  3. 然后通过这两个步骤,构建出一个二维数组,每一个字符对应一个出现的频率。
  4. 然后写一个compareTo方法,对该二维数组的第二个元素进行排序,得到从小到大的一个顺序。
  5. 用构造哈夫曼树的方法,依次递归,找到最小的两个元素然后相加构成一个子树,直到最终的和为1结束。
  6. 通过遍历哈夫曼树,得到每一个元素的编码值,并存进一个新的数组code[]中。
  7. 对从文件中读出的数据进行遍历,并与code[]中的字符进行比较,如若相等,则转换为对应的变码。直至遍历结束,哈夫曼编码完成。
  8. 对于解码,暂时不知道怎么完成。。。。

真正的解决过程

  • 《FIRST》:将文件读出来就让我卡壳了,万事真的开头也难。。。
  • 我百度了一下如何读写文件:

  • 通过学习,我照着编写的读文件的代码:
File file = new File("D:\\20172328lxy\\20172328lxy\\src\\week_10\\homework\\text.txt");Reader reader = new FileReader(file);BufferedReader bufferedReader = new BufferedReader(reader);String temp = bufferedReader.readLine();
  • 同样地,写文件的代码:
 File file2 = new File("D:\\20172328lxy\\20172328lxy\\src\\week_10\\homework\\ciphertext.txt");Writer writer = new FileWriter(file2);writer.write(result1);writer.close();

这样就实现了我预期中的第一步。从把字符集从文件中读出来,并保存在一个数组characters[]里面。

  • 《SECOND》:然后进行计算每一个字符出现的频率。首先用嵌套循环来实现,并把出现的概率存在另一个数组中。真正地初次编完代码,好的,全是0。我继续改,知道在嵌套循环中逻辑没有错误,但是全是0.0。

  • 这就让我有点百思不得其解了,为什么逻辑没有错误,但概率不出现,细细分析一遍,其实是我的除法有问题,在"/"运算中,计算机会自动忽略后面的小数位,所以需要加(float)的操作才化腐朽为神奇。。。(如下图所示)

  • 算频率的时候我用了ASCII表的位置来比对,我觉得自己的这个方法很巧妙。(可能只是我觉得
    还有多种方法可以实现频率的计算~~
double frequency[] = new double[27];int numbers = 0;//空格的个数for (int i = 0; i < characters.length; i++) {if (characters[i] == ' ') {numbers++;}frequency[26] = (float) numbers / characters.length;}System.out.println("字符集为");for (int j = 97; j <= 122; j++) {int number = 0;//给字母计数for (int m = 0; m < characters.length; m++) {if (characters[m] == (char) j) {number++;}frequency[j - 97] = (float) number / characters.length;}System.out.print((char) j + ",");}
  • 《THIRD》:第三部原本想通过这两个步骤,构建出一个二维数组,每一个字符对应一个出现的频率。但是细细想来,二维数组会浪费大量的空间,索性就回过头去写哈夫曼树的构成,参考了一些博客,写出了大体的代码,在广度优先遍历解决完成后,需要找到所有的叶子节点,才能知道每一个字符对应的编码,所以需要记录一个值,再添加子树的时候将“0”和“1”记录下来,最后最好输出在我的广度优先遍历结果中,添加在结点的属性里。
  • 于是我先尝试了一下,用了一个int型的变量加在了huffman树的节点类的属性中,但是出现的结果是:

  • 我找了找规律,最后发现只有0和1的话,加起来很容易就会出现这种情况,而不会反映我的编码,于是我才明白只能用String型来保存这个变量,字符串的相加才能正常出现编码,这样一来就解决了我的问题。
public class Node implements Comparable<Node> {private char data;private double weight;private Node left;private Node right;String codenumber;//这个就是保存0&1的变量public Node(char data, double weight){this.data = data;this.weight = weight;this.codenumber ="";}

  • 《Fourth》:得到每个字符对应的编码后,就可以对文件进行编码了。
//对英文文件进行编码,输出一个编码后的文件String result1 = "";List<Node> temp1 = breadthFirstTraversal(root);for (int i = 0; i < characters.length; i++) {for (int j = 0; j < temp1.size(); j++) {if (characters[i] == temp1.get(j).getData()) {result1 += temp1.get(j).getCodenumber();}}}
  • 再写入文件:
File file2 = new File("D:\\20172328lxy\\20172328lxy\\src\\week_10\\homework\\ciphertext.txt");Writer writer = new FileWriter(file2);writer.write(result1);writer.close();
  • 《Fifth》:对英文文件进行解码,输出一个解码后的文件。在这一部分我没有思路,想了很久还是没什么结果。在这一部分参考了我们班同学20172313余坤澎同学的博客,他的思路很好而且很容易让人理解!根据他的思路,我把遍历出的树保存在一个Node型的列表temp1中,再从temp1中挑出字符和编码分别存放在String型的列表newlist和String型的列表newlist1中,在使用他巧妙的暂时记录点的方法,最后实现了解码。
//对英文文件进行解码,输出一个解码后的文件//将所有具有字符的叶子节点重新保存在一个newlist里面List<String> newlist = new ArrayList<>();for(int m=0;m < temp1.size();m++){if(temp1.get(m).getData()!='无')newlist.add(String.valueOf(temp1.get(m).getData()));}System.out.println("字符:"+newlist);List<String> newlist1 = new ArrayList<>();for(int m=0;m < temp1.size();m++){if(temp1.get(m).getData()!='无')newlist1.add(String.valueOf(temp1.get(m).getCodenumber()));}System.out.println("对应编码:"+newlist1);//先从编完码的文件中读出密文FileReader fileReader = new FileReader("D:\\20172328lxy\\20172328lxy\\src\\week_10\\homework\\ciphertext.txt");BufferedReader bufferedReader1 = new BufferedReader(fileReader);String secretline = bufferedReader1.readLine();//将读出的密文存在secretText列表中List<String> secretText = new ArrayList<String>();for (int i = 0; i < secretline.length(); i++) {secretText.add(secretline.charAt(i) + "");}//解密String result2 = "";//最后的解码结果String current="";// 临时的保存值while(secretText.size()>0) {current = current + "" + secretText.get(0);secretText.remove(0);for (int p = 0; p < newlist1.size(); p++) {if (current.equals(newlist1.get(p))) {result2 = result2 + "" + newlist.get(p);current="";}}}System.out.println("解码后的结果:"+result2);File file3 = new File("D:\\20172328lxy\\20172328lxy\\src\\week_10\\homework\\text1.txt");Writer writer1 = new FileWriter(file3);writer1.write(result2);writer.close();}

最后的结果图


点击找到完整代码

转载于:https://www.cnblogs.com/LXY462283007/p/10100337.html

20172328--蓝墨云班课实验--哈夫曼树的编码相关推荐

  1. 20172305 2018-2019-1 蓝墨云班课实验--哈夫曼树的编码

    20172305 2018-2019-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, ...

  2. 补交20145226蓝墨云班课 -- MyOD

    蓝墨云班课 -- MyOD.java 具体描述: 编写MyOD.java 用java MyOD XXX实现Linux下od -tx -tc XXX的功能. 提交测试代码和运行结果截图,加上学号水印,提 ...

  3. 基于蓝墨云平台的计算机教学,基于蓝墨云班课的中职计算机“分层教学”模式探究...

    崔月娇 一.教学现状概述 一方面,我校是面向全国招生,部分欠发达地区的学生由于资源配置导致计算机基础相当薄弱,而来自发达地区的学生早早地接触了计算机,部分计算机基础操作已相当熟练,学生的计算机水平参差 ...

  4. 补交20145226蓝墨云班课 -- MyCP

    蓝墨云班课 -- MyCP.java 具体描述: 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能,要求MyCP支持两个参数: java MyCP -tx XXX1.txt ...

  5. 蓝墨云班课计算机测试题答案,20155317 第一周蓝墨云班课考题

    20155317 2016-2017-2 蓝墨云班课考题第2周 上周蓝墨云班课考题 1 ( 单选题 | 1 分) Amdahl定律说明,我们对系统的某个部分做出重大改进,可以显著获得一个系统的加速比. ...

  6. 20155317 2016-2017-2 蓝墨云班课考题第2周

    20155317 2016-2017-2 蓝墨云班课考题第2周 三: 1.用gcc -g编译vi输入的代码 2.在main函数中设置一个行断点 3.在main函数增加一个空循环,循环次数为自己学号后4 ...

  7. 使用springboot+vue+element-ui模仿蓝墨云班课

    声明:前端大量CSS样式从原网站复制来的,蓝墨云班课也十分好用,大家可以了解下 项目地址:前端+后端+数据库 https://gitee.com/cao-qiangqiang/a04test07/tr ...

  8. 20162330 第十周 蓝墨云班课 十字链表

    作业要求 画出附件中有向图的十字链表:(附件见下图) 示例分析 示例如下: 分析: ① 首先可以标出各个顶点的序号: ② 找到每个顶点对应的入弧和出弧,可以进行标注: ③ 对于每一行的链表,都会有对应 ...

  9. 补交20145226蓝墨云班课 -- 正则表达式作业

    蓝墨云班课 -- 正则表达式作业 具体描述: 参考老师在博客园的 Intellj IDEA 简易教程中的单元测试,以TDD的放式学习云班课中"正则表达式简易教程.pdf",在此贴出 ...

最新文章

  1. 搭建网站必不可少的知识3
  2. ajax实现简单计算器,一个简单的jQuery计算器实现了连续计算功能
  3. 给博客园加一个会动的小人-spig.js
  4. JavaSE基础复习总结
  5. BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告
  6. .md是什么文件_Element-UI源码阅读之md显示到页面
  7. php三种web开发技术,三种WEB开发主流技术ASP-PHP-JSP的评价
  8. 数据结构员工通讯录管理系统 C语言,数据结构课程设计报告单位员工通讯录管理系统.doc...
  9. C语言预定义宏的使用
  10. 支持全文搜索的桌面搜索工具
  11. 国内三大通信运营商频段制式
  12. 中国首档程序员真人秀,20位选手找bug做模型,结果一开场主办方就惨遭攻击
  13. python微信红包代码_哄女朋友必备之微信自动发红包脚本(python+adb+androidviewclient)...
  14. android原生组件,RN原生的安卓UI组件
  15. fatal: Exiting because of unfinished merge.致命的:由于合并未完成而退出。
  16. Mac升级python3版本
  17. leetCode 357. Count Numbers with Unique Digits | Dynamic Programming | Medium
  18. AD18运行PCB DRC显示一处警告, Design contains shelved or modified (but not repoured) polygons.
  19. NBA勇士败给残阵湖人后....
  20. 程序员福利---免费接口

热门文章

  1. 【总结】alter table *** add constraint *** 用法 . 建立约束 ,主键、外键的SQL语句写法
  2. map在python中是什么意思_【后端开发】map在python中什么意思
  3. python编程计算器_Python设计实现的计算器功能完整实例
  4. aria服务器没有响应,aria2服务器错误
  5. 7. Components
  6. [我所知道的BIOS]-[Jumpless] 4
  7. 扫雷 洛谷p2327
  8. 以太网巨人3Com退出历史舞台
  9. Alibaba Java 2021 技术图谱——学习永无止境
  10. 7-3 试试多线程 (10 分)