哈夫曼編碼

哈夫曼編碼

任務要求

設有字符集: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)把實驗結果截圖上傳到雲班課html

哈夫曼編碼

哈夫曼樹的基本概念

  • 哈夫曼(Huffman)樹又稱做最優二叉樹,它是n個帶權葉子結點構成的全部二叉樹中,帶權路徑長度最小的二叉樹。
  • 「路徑」就是從樹中的一個結點到另外一個結點之間的分支構成的部分,而分支的數目就是路徑長度。
  • 樹的路徑長度:就是從樹根到每一結點的路徑長度之和。
  • 考慮帶權的結點,結點的帶權路徑長度爲:從該結點到樹根之間的路徑長度與結點上權的乘積。
  • 樹的帶權路徑長度WPL(weighted path length):樹中全部葉子結點的帶權路徑長度之和。
  • 假設一個有n個帶權葉子結點的二叉樹,其權值爲{w1,w2,....wn},每一個葉子結點帶權wk,每一個葉子的路徑長度爲 lk,則從根結點

哈夫曼編碼

  • 哈夫曼編碼是哈夫曼樹的一個應用。在數字通訊中,常常須要將傳送的文字轉換成由二進制字符0、1組成的二進制串,這一過程被
    稱爲編碼。在傳送電文時,老是但願電文代碼儘量短,採用哈夫曼編碼構造的電文的總長最短。
  • 由常識可知,電文中每一個字符出現的機率是不一樣的。假定在一份電文中,A,B,C,D四種字符出現的機率是4/10,1/10,3/10,
    2/10,若採用不等長編碼,讓出現頻率低的字符具備較長的編碼,這樣就有可能縮短傳送電文的總長度。

分析及實現過程

  • 讀取文件中的字符並存入數組

讀取文件node

File file = new File("/Users/wby/IdeaProjects/NEW/HaFuManTree/src/test.txt");
        //mac 設置路徑的方法不太同樣:/Users/wby/IdeaProjects/NEW/HaFuManTree/src/test.txt
        Reader reader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(reader);
        String temp = bufferedReader.readLine();

存入數組數組

char characters[] = new char[temp.length()];
        for (int i = 0; i < temp.length(); i++) {
            characters[i] = temp.charAt(i);
        }
  • 計算每一個字母出現的頻率,存入另外一數組

計算出頻率存到frequency[]並輸出編碼

double frequency[] = new double[27];
        //最後一個是加入空格
        System.out.println("機率爲:");
        int num = 0;
        for (int i = 0; i < characters.length; i++) {
            if (characters[i] == ' ') {
                num++;
            }
            frequency[26] = (float) num / characters.length;
        }
        for (int j = 97,i=0; j <= 122; j++,i++) {
            //計數
            int number = 0;
            for (int m = 0; m < characters.length; m++) {
                if (characters[m] == (char) j) {
                    number++;
                }
                /*frequency[j - 97] = (float) number / characters.length;*/
                frequency[j - 97] = (float) number / characters.length;
            }
          //  System.out.println("每一個字符的機率是" + "\n" + Arrays.toString(frequency));
            System.out.println();
            System.out.print((char) j + ":"+frequency[i]);
        }
  • 構造哈夫曼樹

設置結點數組,有兩個或兩個以上,最後一個結點設置爲根結點.net

while (nodes.size() > 1) {
            Collections.sort(nodes);
            HaFuMan left = nodes.get(nodes.size() - 1);
            HaFuMan right = nodes.get(nodes.size() - 2);
            HaFuMan parent = new HaFuMan('無', left.getWeight() + right.getWeight());
            parent.setLeft(left);
            left.setCode("0");
            parent.setRight(right);
            right.setCode("1");
            nodes.remove(left);
            nodes.remove(right);
            nodes.add(parent);
  }

左子樹爲0右子樹爲1設計

if (root != null) {//判斷根是否爲空
            queue.offer(root);
            root.getLeft().setCode(root.getCode() + "0");
            root.getRight().setCode(root.getCode() + "1");
        }

判斷不爲null,將它加入到隊列code

if (node.getRight() != null) {
                queue.offer(node.getRight());
                node.getRight().setCode(node.getCode() + "1");
            }

判斷根是否爲空htm

if (node.getLeft() != null) {
                queue.offer(node.getLeft());
                node.getLeft().setCode(node.getCode() + "0");
  • 新建文件夾編碼並輸出

設置編碼blog

String result1 = "";

        List<HaFuMan> temp1 = HaFuMan.breadth(root);

        for (int i = 0; i < characters.length; i++) {
            for (int j = 0; j < temp1.size(); j++) {

                if (characters[i] == temp1.get(j).getData()) {
                    result1 += temp1.get(j).getCode();
                }
            }
        }

設置文件輸入流並打印隊列

System.out.println("\n"+"編碼:");
        System.out.println(result1);
        File file2 = new File("/Users/wby/IdeaProjects/NEW/HaFuManTree/src/test2.txt");
        Writer writer = new FileWriter(file2);
        writer.write(result1);
        writer.close();
  • 新建文件夾解碼並輸出

設置解碼

String result2 = "";
        String current="";//定義最後的解碼過程
        while(sT.size()>0) {
            current = current + "" + sT.get(0);
            sT.remove(0);
            for (int p = 0; p < newlist1.size(); p++) {
                if (current.equals(newlist1.get(p))) {
                    result2 = result2 + "" + newlist.get(p);
                    current="";
                }

將文件解密並存入test3輸出

System.out.println("\n"+"解碼:"+"\n"+"F"+result2);
    File file3 = new File("/Users/wby/IdeaProjects/NEW/HaFuManTree/src/test3.txt");
    Writer writer1 = new FileWriter(file3);
    writer1.write(result2);
    writer.close();

實現結果

參考資料

哈夫曼樹原理,及構造方法
mac的路徑怎麼寫
哈夫曼樹及其應用

相關文章
相關標籤/搜索