哈夫曼編碼測試

實驗目的

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

實驗過程

HuffmanNode設計this

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

    }
}

實驗結果

碼雲連接code

相關文章
相關標籤/搜索