• 哈夫曼编码


    20172319 2018.12.07

    哈夫曼编码

    课程名称:《程序设计与数据结构》  
    学生班级:1723班  
    学生姓名:唐才铭  
    学生学号:20172319 
    实验教师:王志强老师
    课程助教:张师瑜学姐、张之睿学长
    实验时间:2018年12月07日
    必修/选修:必修
    

    目录


    实践内容

    设有字符集: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)把实验结果截图上传到云班课
    满分:6分。
    酌情打分。

    返回目录


    实践要求

    1. 完成蓝墨云上哈夫曼编码测试相关的活动,及时提交代码运行截图和码云Git链接,截图要有学号水印,否则会扣分。
    2. 完成实验、撰写实验报告,实验报告以博客方式发表在博客园,注意实验报告重点是运行结果,遇到的问题(工具查找,安装,使用,程序的编辑,调试,运行等)、解决办法(空洞的方法如“查网络”、“问同学”、“看书”等一律得0分)以及分析(从中可以得到什么启示,有什么收获,教训等)。报告可以参考范飞龙老师的指导
    3. 严禁抄袭,有该行为者实验成绩归零,并附加其他惩罚措施。

    返回目录


    实践步骤

    设有字符集: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)把实验结果截图上传到云班课
    满分:6分。
    酌情打分。

    前期准备:

    1. 预先下载安装好IDEA 。

    需求分析:

    • 需要了解、理解哈夫曼编码的相关知识

    返回目录


    代码实现及解释

    (1)准备一个包含26个英文字母的英文文件(可以不包含标点符号等),统计各个字符的概率

    • 在src目录下右键,新建文件,输入文件名,文本文件,之后将自己所需内容放入即可。
    • 读取文件内容:
    File fromFile = new File("English-text");
            // 创建字符输入流
            Reader reader = null;
            String data = "";
    
            List temp = new LinkedList();
            try {
                reader = new FileReader(fromFile);
                // 循环读取(打印)
                int content = reader.read();
                while (content != -1) {
                    System.out.print((char) content);
                    temp.add(content);
                    data += (char) content;
                    content = reader.read();
                }
                System.out.println();
    
    • 文件中可能有些字符如: 之类的,可以使用replace方法将其替换成“”字符。

    • 实现截图如下:

    • 统计各个字符出现的概率:

    public static void printStr(String str, int[] Probabilities, String[] Data ) {
            if (str == null || "".equals(str)) {
                System.out.println("字符串不能为空!");
                return;
            }
            Map<String, Integer> pMap = new HashMap<String, Integer>();
            String[] split = str.split("");
            for (int i = 0; i < split.length; i++) {
                if (!"".equals(split[i]) && pMap.containsKey(split[i])) {
                    pMap.put(split[i], pMap.get(split[i]) + 1);
                } else if (!"".equals(split[i])) {
                    pMap.put(split[i], 1);
                }
            }
            Set<String> keySet = pMap.keySet();
            int total = 0;
            int i = 0;
            for (String string : keySet) {
                total += pMap.get(string);
            }
            for (String string : keySet) {
                Probabilities[i] =pMap.get(string)  ;
                Data[i] = string;
                System.out.println(string + "出现的概率:" + "分数: " + pMap.get(string) + "/" + total
                        + "	" + "小数:" + (double) pMap.get(string) / total);
                i++;
            }
        }
    
    • 实现截图如下:

    (2)构造哈夫曼树

     public static <T> HuffmanNode<T> CreatTree(List<HuffmanNode<T>> HuffmanNode) {
                while (HuffmanNode.size() > 1) {
                    Collections.sort(HuffmanNode);
                    HuffmanNode<T> left = HuffmanNode.get(HuffmanNode.size() - 1);
                    HuffmanNode<T> right = HuffmanNode.get(HuffmanNode.size() - 2);
                    HuffmanNode<T> parent = new HuffmanNode<T>(null,left.getWeight()
                            + right.getWeight());
                    parent.setLeftChild(left);
                    parent.setRightChild(right);
                    HuffmanNode.remove(left);
                    HuffmanNode.remove(right);
                    HuffmanNode.add(parent);
                }
                return HuffmanNode.get(0);
            }
    
            public static <T> List<HuffmanNode<T>> breadth(HuffmanNode<T> Root) {
                List<HuffmanNode<T>> list = new ArrayList<HuffmanNode<T>>();
                Queue<HuffmanNode<T>> queue = new ArrayDeque<HuffmanNode<T>>();
    
                if (Root != null) {
                    queue.offer(Root);
                }
    
                while (!queue.isEmpty()) {
                    list.add(queue.peek());
                    HuffmanNode<T> node = queue.poll();
    
                    if (node.getLeftChild() != null) {
                        queue.offer(node.getLeftChild());
                    }
    
                    if (node.getRightChild() != null) {
                        queue.offer(node.getRightChild());
                    }
                }
                return list;
            }
        }
    
    • 实现截图如下:

    (3)对英文文件进行编码,输出一个编码后的文件

     public String toHufmCode(String str) {
    
                for (int i = 0; i < str.length(); i++) {
                    String c = str.charAt(i) + "";
                    search(root, c);
                }
    
                return hfmCodeStr;
            }
    
    
            private void search(HNode root, String c) {
                if (root.lChild == null && root.rChild == null) {
                    if (c.equals(root.data)) {
                        hfmCodeStr += root.code;
                    }
                }
                if (root.lChild != null) {
                    search(root.lChild, c);
                }
                if (root.rChild != null) {
                    search(root.rChild, c);
                }
            }
    
    
    • 实现截图如下:

    (4)对编码文件进行解码,输出一个解码后的文件

    public String CodeToString(String codeStr) {
    
                int start = 0;
                int end = 1;
    
                while(end <= codeStr.length()){
                    target = false;
                    String s = codeStr.substring(start, end);
                    matchCode(root, s);
                    if(target){
                        start = end;
                    }
                    end++;
                }
    
                return result;
            }
    
            private void matchCode(HNode root, String code){
                if (root.lChild == null && root.rChild == null) {
                    if (code.equals(root.code)) {
                        result += root.data;
                        target = true;
                    }
                }
                if (root.lChild != null) {
                    matchCode(root.lChild, code);
                }
                if (root.rChild != null) {
                    matchCode(root.rChild, code);
                }
    
            }
        }
    
    • 实现截图如下:

    返回目录


    测试过程及遇到的问题

    • 问题1: 无任何记录。
    • 解决:

    返回目录


    分析总结

    返回目录


    代码托管

    返回目录


    参考资料

    Intellj IDEA 简易教程

    返回目录

  • 相关阅读:
    Linux中find命令用法全汇总,看完就没有不会用的!
    ubuntu16.04 通过命令,修改屏幕分辨率
    Linux下如何查看哪些进程占用的CPU内存资源最多
    shell脚本 在后台执行de 命令 >> 文件 2>&1 将标准输出与错误输出共同写入到文件中(追加到原有内容的后面)
    ef linq 访问视图返回结果重复
    asp.net core web 本地iis开发
    jQuery控制TR显示隐藏
    mvc EF 从数据库更新实体,添加视图实体时添加不上的问题
    无法确定依赖操作的有效顺序。由于外键约束、模型要求或存储生成的值,因此可能存在依赖关系
    还原差异备份——因为没有文件可用于前滚
  • 原文地址:https://www.cnblogs.com/Tangcaiming/p/10111730.html
Copyright © 2020-2023  润新知