zoukankan      html  css  js  c++  java
  • 哈夫曼编码对文件进行加密解密

    20182312 2019-2020-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)对编码文件进行解码,输出一个解码后的文件
    (5)撰写博客记录实验的设计和实现过程,并将源代码传到码云
    (6)把实验结果截图上传到云班课

    哈夫曼编码原理

    • 霍夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的路径长度是从树根到每一结点的路径长度之和,记为WPL=(W1XL1+W2XL2+W3XL3+...+WnXLn),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以证明霍夫曼树的WPL是最小的。

    实践过程

    1.循环取出文件中的数据组成字符串

    public static String makecode(FileInputStream stream) throws IOException {
            BufferedInputStream in = new BufferedInputStream(stream);
            byte[] bytes = new byte[2048];
            int n = -1;
            String a = null;
            while ((n = in.read(bytes, 0, bytes.length)) != -1) {
                a = new String(bytes, 0, n, "GBK");
            }
    

    2.嵌套循环,外层循环控制从a到null的字符,内层遍历字符串,对字符的出现频率进行计数

    public static void count(String str){
            for (int i = 0;i < 27;i++){
                int num = 0;
                for (int j = 0;j < str.length();j++){
                    if (str.charAt(j) == word[i]){
                        num++;
                    }
                }
                number[i] += num;
            }
        }
    
        public static char[] getWord() {
            return word;
        }
    
        public static int[] getNumber() {
            return number;
        }
    

    3.根据哈夫曼编码的原理自底而上建立哈夫曼树

    public class HuffmanTree {
        public static HuffmanNode createTree(List<HuffmanNode<String>> nodes) {
            while (nodes.size() > 1){
                Collections.sort(nodes);
                HuffmanNode left = nodes.get(nodes.size() - 2);
                left.setCode(0 + "");
                HuffmanNode right = nodes.get(nodes.size() - 1);
                right.setCode(1 + "");
                HuffmanNode parent = new HuffmanNode(left.getWeight() + right.getWeight(), null);
                parent.setLeft(left);
                parent.setRight(right);
                nodes.remove(left);
                nodes.remove(right);
                nodes.add(parent);
            }
            return nodes.get(0);
        }
    

    4.令树中元素入队并编码

     public static List<HuffmanNode> BFS(HuffmanNode root){
            Queue<HuffmanNode> queue = new ArrayDeque<HuffmanNode>();
            List<HuffmanNode> list = new java.util.ArrayList<HuffmanNode>();
    
            if (root != null){
                // 将根元素加入队列
                queue.offer(root);
                root.getLeft().setCode(root.getCode() + "0");
                root.getRight().setCode(root.getCode() + "1");
            }
    
            while (!queue.isEmpty()){
                list.add(queue.peek());
                HuffmanNode node = queue.poll();
                if (node.getLeft() != null){
                    queue.offer(node.getLeft());
                    node.getLeft().setCode(node.getCode() + "0");
                }
                if (node.getRight() != null){
                    queue.offer(node.getRight());
                    node.getRight().setCode(node.getCode() + "1");
                }
            }
            return list;
        }
    

    5.解码并写入文件

           List<String> list4 = new ArrayList<>();
            for (int i = 0;i < result.length();i++){
                list4.add(result.charAt(i) + "");
            }
            String temp = "";
            String temp1 = "";
            while (list4.size() > 0){
                temp += "" + list4.get(0);
                list4.remove(0);
                for (int i = 0;i < list3.size();i++){
                    if (temp.equals(list3.get(i))){
                        temp1 += "" + list2.get(i);
                        temp = "";
                    }
                }
            }
            System.out.println("文件解码结果为: " + temp1);
            File file = new File("D:\Development\123\src\word.txt");
            Writer out = new FileWriter(file);
            out.write(result);
            out.close();
        }
    

    测试结果


    代码链接

  • 相关阅读:
    获取ocx运行路径的另一种方法
    使用D3D渲染YUV视频数据
    C++(MFC)中WebBrowser去除3D边框的方法(实现IDocHostUIHandler接口)
    ActiveX控件的安全初始化和脚本操作 和 数字签名SIGN
    解决Eclipse中的卡死现象
    Http请求头和响应头
    HTTP请求头与响应头
    centos7 Mariadb5.5升级到Mariadb10.2
    window下利用navicat访问Linux下的mariadb数据库
    在Linux上安装及配置MariaDB
  • 原文地址:https://www.cnblogs.com/shouko/p/11914269.html
Copyright © 2011-2022 走看看