哈夫曼编码

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();
  • 文件中可能有些字符如:\n \r之类的,可以使用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
                    + "\t" + "小数:" + (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 简易教程

返回目录

posted @ 2018-12-12 23:45  ⊙ω⊙  阅读(210)  评论(0编辑  收藏