zoukankan      html  css  js  c++  java
  • 哈夫曼编码

    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内核分析——扒开系统调用的三层皮(下)
    Linux内核分析——第二章 从内核出发
    Linux内核分析——第一章 Linux内核简介
    Linux内核分析——扒开系统调用的三层皮(上)
    Linux内核分析——构造一个简单的Linux系统MenuOS
    Linux内核分析——操作系统是如何工作的
    Linux内核分析——计算机是如何工作的
  • 原文地址:https://www.cnblogs.com/Tangcaiming/p/10111730.html
Copyright © 2011-2022 走看看