本篇博文用java構造了哈夫曼樹
源碼分享在github:數據結構,當然你也可以從下面的代碼片中獲取
哈夫曼樹節點類 HuffmanNode.java
package code.tree;
/*
* 哈夫曼樹的節點類
* */
public class HuffmanNode {
public int weight; //節點的權值
public int flag; //節點是否加入哈夫曼樹的標誌
public HuffmanNode parent,lChild,rChild;//父節點和左右孩子節點
public HuffmanNode(){
this(0); //默認構造的節點權值爲0
}
public HuffmanNode(int weight){
this.weight = weight; //構造具有權值的節點
flag = 0;
parent = lChild = rChild = null;
}
}
哈夫曼樹類 HuffmanTree.java
public class HuffmanTree {
//求哈夫曼編碼的算法,W存放n個字符的權值(均 > 0)
public int [] [] huffmanCoding(int [] W){
int n = W.length; //字符個數
int m = 2*n - 1; //哈夫曼樹的節點數
HuffmanNode [] HN = new HuffmanNode[m]; //定義一個霍夫曼節點的數組
int i;
for (i = 0;i < n;i++){
HN[i] = new HuffmanNode(W[i]); //構造n個具有權值的節點,因爲並不是每一個節點都是有權值的,只有在邊上的纔有
}
//開始建立哈夫曼樹
for (i = n;i < m;i++){ //已經有了n個節點,還需要構建 m-n 個出來
//在 HN[0..i-1] 選擇不在哈夫曼樹中且weight最小的兩個節點 min1 和 min2
HuffmanNode min1 = selectMin(HN,i-1);
min1.flag = 1;
HuffmanNode min2 = selectMin(HN,i-1);
min2.flag = 1;
//構造min1和min2的父節點,並修改其父節點的權值
HN[i] = new HuffmanNode();
min1.parent = HN[i];
min2.parent = HN[i];
HN[i].lChild = min1;
HN[i].rChild = min2;
HN[i].weight = min1.weight+min2.weight;
}
//從葉子到根逆向求每個字符的哈夫曼碼
int[][] HuffCode = new int[n][n]; //分配n個字符編碼存儲空間
for (int j = 0;j < n;j++){
int start = n-1; //編碼的開始位置,初始化爲數組的結尾
for (HuffmanNode c = HN[j],p = c.parent;p!=null;c = p,p = p.parent){
//從葉子到根逆向求編碼
if (p.lChild.equals(c)){
//左孩子編碼爲0
HuffCode[j][start--] = 0;
}else {
HuffCode[j][start--] = 1;
}
}
HuffCode[j][start] = -1; //編碼的開始標誌爲-1,編碼是-1之後的0,1序列
}
return HuffCode;
}
//在 HN[0..i-1] 選擇不在哈夫曼樹中且weight最小的節點
private HuffmanNode selectMin(HuffmanNode[] HN,int end){
HuffmanNode min = HN[end];
for (int i = 0;i <= end;i++){
HuffmanNode h = HN[i];
if (h.flag == 0&& h.weight < min.weight){ //如果不在哈夫曼樹中且weight最小的節點
min = h;
}
}
return min;
}
//測試代碼
public static void main(String [] args){
int [] W = {23,11,5,3,29,14,7,8}; //初始化權值
HuffmanTree T = new HuffmanTree(); //構造哈夫曼樹
int [][]HN = T.huffmanCoding(W); //求哈夫曼編碼
System.out.println("哈夫曼編碼爲:");
for (int i = 0;i<HN.length;i++){
System.out.print(W[i]+" ");
for (int j = 0;j<HN[i].length;j++){
if (HN[i][j] == -1){
//開始標識符讀到數組結尾
for (int k = j+1;k<HN[i].length;k++){
System.out.print(HN[i][k]);//輸出
}
break;
}
}
System.out.println();//換行
}
}
}
總結
數據結構這個系列是我學習時做的筆記,會持續更新,詳見我的github(地址在文章開頭)或我的數據結構系列其他博文,感覺不錯的話,關注一下吧!