1.定義:給定n個權值作為n個葉子結點,構造一棵二叉樹,若該樹的帶權路徑長度達到最小,稱這樣的二叉樹為最優二叉樹,也稱為哈夫曼樹(huffman tree)。哈夫曼樹是帶權路徑長度最短的樹,權值較大的結點離根較近。
2.術語
(01) 路徑和路徑長度
定義:在一棵樹中,從乙個結點往下可以達到的孩子或孫子結點之間的通路,稱為路徑。通路中分支的數目稱為路徑長度。若規定根結點的層數為1,則從根結點到第l層結點的路徑長度為l-1。
例子:100和80的路徑長度是1,50和30的路徑長度是2,20和10的路徑長度是3。
(02) 結點的權及帶權路徑長度
定義:若將樹中結點賦給乙個有著某種含義的數值,則這個數值稱為該結點的權。結點的帶權路徑長度為:從根結點到該結點之間的路徑長度與該結點的權的乘積。
例子:節點20的路徑長度是3,它的帶權路徑長度= 路徑長度 * 權 = 3 * 20 = 60。
(03) 樹的帶權路徑長度
定義:樹的帶權路徑長度規定為所有葉子結點的帶權路徑長度之和,記為wpl。
例子:示例中,樹的wpl= 1100 + 280 + 320 + 310 = 100 + 160 + 60 + 30 = 350。
3.構造
假設有n個權值,則構造出的哈夫曼樹有n個葉子結點。 n個權值分別設為 w1、w2、…、wn,則哈夫曼樹的構造規則為:
(1) 將w1、w2、…,wn看成是有n 棵樹的森林(每棵樹僅有乙個結點);
(2) 在森林中選出兩個根結點的權值最小的樹合併,作為一棵新樹的左、右子樹,且新樹的根結點權值為其左、右子樹根結點權值之和;
(3)從森林中刪除選取的兩棵樹,並將新樹加入森林;
(4)重複(2)、(3)步,直到森林中只剩一棵樹為止,該樹即為所求得的哈夫曼樹。
public class huffmantreenode implements comparable
@override
public int compareto(huffmantreenode huffmantreenode)
1.定義乙個根節點
private huffmantreenode mroot; // 根結點
2.建構函式
這裡將會使用乙個最小堆,用來每次取出權值最小的兩個哈夫曼樹結點來構造成乙個新的哈夫曼樹結點,並新增到最小堆中去。直到所有元素構造成乙個哈夫曼樹結點,設為根節點。
public huffmantree(huffmantreenode array)
}
解碼這裡一開始的思路是從編碼結果中取出若干元素,對比各個字元編碼結果,得到解碼結果,沒有去做,感覺太麻煩,而且沒有規律性,很難做。
參看了這篇部落格:哈夫曼樹及解碼
自己才理清思路,開始編寫,
這個思路是:從編碼結果逐個讀取,若為0,則指向結點左孩子,反之為其右孩子,如果其沒有左右孩子,便為我們所找的葉子結點,將其對應元素新增進來,並重新從根結點開始,直至讀取完畢。
//進行解碼
string result2 = "";
for (int i = 0; i < s1.length(); i++)
} else }}
if (huffmantreenode.getleft() == null && huffmantreenode.getright() == null)
}
構造哈夫曼樹,並利用哈夫曼樹進行編碼解碼
哈夫曼樹詳解
哈夫曼樹及解碼
哈夫曼編碼測試
設有字符集 s 給定乙個包含26個英文本母的檔案,統計每個字元出現的概率,根據計算的概率構造一顆哈夫曼樹。並完成對英文檔案的編碼和解碼。要求 1 準備乙個包含26個英文本母的英文檔案 可以不包含標點符號等 統計各個字元的概率 2 構造哈夫曼樹 3 對英文檔案進行編碼,輸出乙個編碼後的檔案 4 對編碼...
哈夫曼編碼測試
在計算機資料處理中,霍夫曼編碼使用變長編碼表對源符號 如檔案中的乙個字母 進行編碼,其中變長編碼表是通過一種評估 符號出現機率的方法得到的,出現機率高的字母使用較短的編碼,反之出現機率低的則使用較長的編碼,這便使編碼之後的字串的平均長度 期望值降低,從而達到無失真壓縮資料的目的。例如,在英文中,e的...
哈夫曼編碼測試
把字元從檔案中取出來,這是以前學過的io流實現的。統計出現的字元及頻率,將各個字元建立為葉子結點,頻率為結點的權值,用鍊錶儲存這些葉子結點。將所有帶權值的結點按權值從小到大排列 依次選取權值最小的結點放在樹的底部,權值小的在左邊 取出的結點相當於從這些結點的集合中剔除 生成乙個新節點作為這兩個結點的...