• 20182323 哈夫曼编码测试


    20182323 哈夫曼编码测试

    课程:《程序设计与数据结构》
    班级: 1823
    姓名: 曹骞
    学号: 20182323
    实验教师:王志强
    实验日期:2019年10月21日
    必修/选修: 必修

    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,y,z}。

    给定一个包含26个英文字母的文件,统计每个字符出现的概率,根据计算的概率构造一颗哈夫曼树。

    并完成对英文文件的编码和解码。

    要求:

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

    2.构造哈夫曼树

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

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

    2.实现过程

    哈夫曼树的建立
    (1) 8个结点的权值大小如下:

    (2). 从19,21,2,3,6,7,10,32中选择两个权小结点。选中2,3。同时算出这两个结点的和5。

    (3). 从19,21,6,7,10,32,5中选出两个权小结点。选中
    5,6。同时计算出它们的和11。

    (4). 从19,21,7,10,32,11中选出两个权小结点。选中7,10。同时计算出它们的和17。(PS:这时选出的两个数字都不是已经构造好的二叉树里面的结点,所以要另外开一棵二叉树;或者说,如果两个数的和正好是下一步的两个最小数的其中的一个,那么这个树直接往上生长就可以了,如果这两个数的和比较大,不是下一步的两个最小数的其中一个,那么就并列生长。)

    (5). 从19,21,32,11,17中选出两个权小结点。选中11,17。同时计算出它们的和28。

    (6). 从19,21,32,28中选出两个权小结点。选中19,21。同时计算出它们的和40。另起一颗二叉树。

    (7). 从32,28, 40中选出两个权小结点。选中28,32。同时计算出它们的和60。

    (8). 从 40, 60中选出两个权小结点。选中40,60。同时计算出它们的和100。 好了,此时哈夫曼树已经构建好了。

    以下为核心代码:

     Node createTree(List<Node> nodes) {
           
            while (nodes.size() > 1) {
                quickSort(nodes);
                
                Node left = nodes.get(nodes.size() - 1);
                Node right = nodes.get(nodes.size() - 2);
    
                Node parent = new Node(null, left.weight + right.weight);
    
                parent.leftChild = left;
                parent.rightChild = right;
    
                nodes.remove(nodes.size() - 1);
                nodes.remove(nodes.size() - 1);
    
                nodes.add(parent);
            }
    
            return nodes.get(0);
    
    • 以左为0,右为1,给字母编码
     public void setCode(Node root) {
    
            if (root.leftChild != null) {
                root.leftChild.code = root.code + "0";
                setCode(root.leftChild);
            }
    
            if (root.rightChild != null) {
                root.rightChild.code = root.code + "1";
                setCode(root.rightChild);
            }
    
        }
        
     public class Node<E> {
            E data;
            public String code = "";
            double weight;
            Node leftChild;
            Node rightChild;
    
            public Node(E data, double weight) {
                super();
                this.data = data;
                this.weight = weight;
            }
    
        }
    
    • 对英文文件进行编码
     private String hfmCodeStr = "";
     
        public String toHufmCode(String str,Node root) {
    
            for (int i = 0; i < str.length(); i++) {
               char c = str.charAt(i) ;
                search(root, c);
            }
            return hfmCodeStr;
        }
    
        private void search(Node root, char c) {
            if (root.leftChild == null && root.rightChild == null) {
                if (c == (char)root.data) {
                    hfmCodeStr += root.code; // 找到字符,将其哈夫曼编码拼接到最终返回二进制字符串的后面
                }
            }
            if (root.leftChild != null) {
                search(root.leftChild, c);
            }
            if (root.rightChild != null) {
                search(root.rightChild, c);
            }
    
        }
    
    • 对编码文件进行解码
     String result="";
        boolean target = false; 
        public String CodeToString(String codeStr,Node root) {
    
            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(Node root, String code){
            if (root.leftChild == null && root.rightChild == null) {
                if (code.equals(root.code)) {
                    result += root.data; // 找到对应的字符,拼接到解码字符穿后
                    target = true; // 标志置为true
                }
            }
            if (root.leftChild != null) {
                matchCode(root.leftChild, code);
            }
            if (root.rightChild != null) {
                matchCode(root.rightChild, code);
            }
        }
    
    • 最终结果截图

    其他(感悟、思考等)

    要想进步,就只有吸取教训,成功的经验都是歪曲的,成功了,想怎么说都可以,失败者没有发言权,可是,你可以通过他的事例反思,总结。教训,不仅要从自己身上吸取,还要从别人身上吸取。
    ——马云

  • 相关阅读:
    webservice
    AppDomain (转)
    Apache和Nginx防盗链的几种配置方法
    优化PHP代码的40条建议
    file_get_contents无法请求https连接的解决方法
    PHP SPL
    Ubuntu 查看系统信息
    PHP导出Excel
    mysql集群
    配置yum源的两种方法
  • 原文地址:https://www.cnblogs.com/caoqian1314/p/11922327.html
Copyright © 2020-2023  润新知