• 哈夫曼编码测试


    实验目的

    设有字符集: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分。

    实验过程

    HuffmanNode设计

    public class Node { 
        public String code = "";
    public String data = ""; 
    public int count;
    public Node lChild; 
    public Node rChild; 
    public Node() { 
        
    }
     public Node(String data, int count) { 
        this.data = data; 
    this.count = count; 
    } 
    public Node(int count, Node lChild, Node rChild) 
        { 
        this.count = count; 
        this.lChild = lChild;
        this.rChild = rChild; 
        } 
    public Node(
          String data, 
          int count, 
          Node lChild,
          Node rChild) { 
        this.data = data; 
        this.count = count; 
        this.lChild = lChild; 
        this.rChild = rChild;
    } 
    }
    

    哈夫曼树构造分为以下几步:

    1. 统计出现的字符及频率
    2. 将各个字符创建为叶子结点,频率为结点的权值,用链表保存这些叶子结点
    3. 将结点队列中的结点按权值升序排列
    4. 取出权值最小的两个结点构建父节点(要从链表中删除取出的结点),将新生成的父节点添加到结点链表,并从新排序
    5. 重复4步骤,直到只剩下一个结点
    6. 返回最后的结点,即为哈夫曼树的根节点。
     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);
        }
    

    编解码实现:

    private String hfmCodeStr = "";// 哈夫曼编码连接成的字符串
    
        /**
         * 编码
         * @param str
         * @return
         */
        public String toHufmCode(String str) {
    
            for (int i = 0; i < str.length(); i++) {
                String c = str.charAt(i) + "";
                search(root, c);
            }
    
            return hfmCodeStr;
        }
    
        /**
         * 
         * @param root 哈夫曼树根节点
         * @param c 需要生成编码的字符
         */
        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);
            }
        }
    
    
        // 保存解码的字符串
        String result="";
        boolean target = false; // 解码标记
        /**
         * 解码
         * @param codeStr
         * @return
         */
        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); // 解码
                // 每解码一个字符,start向后移
                if(target){
                    start = end;
                }
                end++;
            }
    
            return result;
        }
    
        /**
         * 匹配字符哈夫曼编码,找到对应的字符
         * @param root 哈夫曼树根节点
         * @param code 需要解码的二进制字符串
         */
        private void matchCode(HNode root, String code){
            if (root.lChild == null && root.rChild == null) {
                if (code.equals(root.code)) {
                    result += root.data; // 找到对应的字符,拼接到解码字符穿后
                    target = true; // 标志置为true
                }
            }
            if (root.lChild != null) {
                matchCode(root.lChild, code);
            }
            if (root.rChild != null) {
                matchCode(root.rChild, code);
            }
    
        }
    }
    

    实验结果

    码云链接

  • 相关阅读:
    idea使用配置lombok插件
    微服务框架搭建总结点(一):Springboot整合log4j2日志
    git使用笔记:git commit后,如何撤销commit
    SQL Server中char,varchar,nchar, nvarchar的区别
    SQL插入语句插入自增的主键后,如何获取这个新增的主键值
    Linq分组后,再对分组后的每组进行内部排序,获取每组中的第一条记录
    Flutter 笔记
    gch
    JVM内存观察
    mybatis for 循环 中oracle in 条件后 多余1000条处理
  • 原文地址:https://www.cnblogs.com/huzhitao/p/10111433.html
Copyright © 2020-2023  润新知