哈夫曼編碼測試
測試要求
- 設有字符集: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)把實驗結果截圖上傳到雲班課
設計思路
- 把字符從文件中取出來,這是之前學過的IO流實現的。
- 統計出現的字符及頻率,將各個字符建立爲葉子結點,頻率爲結點的權值,用鏈表保存這些葉子結點。
- 將全部帶權值的結點按權值從小到大排列;
- 依次選取權值最小的結點放在樹的底部,權值小的在左邊(取出的結點至關於從這些結點的集合中剔除);
- 生成一個新節點做爲這兩個結點的父節點,且父節點的權值等於這兩個結點權值之和,而後要把這個新結點放回咱們須要構成樹的結點中,繼續進行排序;
- 重複上述二、3步驟,直至所有節點造成一棵樹,此樹即是哈夫曼樹,最後生成的結點即爲根節點。這樣構成的哈夫曼樹,全部的存儲有信息的結點都在葉子結點上。
- 解碼就是在二進制字符串中匹配字符哈夫曼編碼,找到對應的字符不斷輸出。
- 理論上來講就是這麼幾步了。
操做過程
結點類
- 我是在二叉樹結點的基礎上修改一下,主要是多定義了節點的哈夫曼編碼、節點的權值。
public class HNode {
public String code = "";// 節點的哈夫曼編碼
public String data = "";// 節點的數據
public int count;// 節點的權值
public HNode left;
public HNode right;
public HNode(String data, int count) {
this.data = data;
this.count = count;
}
public HNode(int count, HNode lChild, HNode rChild) {
this.count = count;
this.left = lChild;
this.right = rChild;
}
public HNode getLeft() {
return left;
}
public void setLeft(HNode left) {
this.left = left;
}
public HNode getRight() {
return right;
}
public void setRight(HNode right) {
this.right = right;
}
}
哈夫曼樹類
private void Sort(LinkedList<HNode> nodelist) {
for (int i = 0; i < nodelist.size() - 1; i++) {
for (int j = i + 1; j < nodelist.size(); j++) {
HNode temp;
if (nodelist.get(i).count > nodelist.get(j).count) {
temp = nodelist.get(i);
nodelist.set(i, nodelist.get(j));
nodelist.set(j, temp);
}
}
}
}`
- 以後取出權值最小的兩個節點,生成一個新的父節點,刪除權值最小的兩個節點,將父節點存放到列表中,並不斷重複,直到獲得根節點。
- 須要解碼的二進制字符串,匹配字符哈夫曼編碼,找到對應的字符
測試類
File file = new File("C:\\Users\\lenovo\\IdeaProjects\\why20172321\\src\\week10\\哈夫曼樹解碼\\hfm.txt");
Reader reader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(reader);
String data = bufferedReader.readLine();
- 輸出一下每一個數的機率和對應的哈夫曼編碼。
- 獲得編碼結果並輸入文件,而後讀取文件進行解碼,並將解碼內容輸出。
測試結果