哈夫曼編碼對文件進行加密解密


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();
    }

測試結果


代碼鏈接


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM