對某一字符串的最短二進制編碼稱爲赫夫曼編碼。
package tree;
import java.util.Stack;
public class HuffmanTree {
public static int[] min (Note[] note,int n) { //選出所有樹中權值最小的兩個
int min1 = Integer.MAX_VALUE - 1;
int j = -1;
int min2 = Integer.MAX_VALUE;
int k = -1;
for (int i = 0;i < n; i ++) {
if (note[i].parent == -1 && note[i].weight < min1) {
min1 = note[i].weight;
j = i;
} else if (note[i].parent == -1 && note[i].weight < min2) {
min2 = note[i].weight;
k = i;
}
}
return new int[]{j,k};
}
public static void merge (Note[] note, int i, int j, int n) { //合併兩棵樹
note[i].parent = note[j].parent = n;
note[n] = new Note(note[i].weight + note[j].weight,i,j,-1);
}
public static StringBuffer[] getCode (Note[] note) {
int n = (note.length + 1) / 2;
StringBuffer[] code = new StringBuffer[n];
Stack<String> tem = new Stack<>();
for (int i = 0; i < n; i ++) {
int c = i;
int p;
while(note[c].parent != -1) {
p = note[c].parent;
if(note[p].lChild == c) {
tem.push("0");
} else {
tem.push("1");
}
c = p;
}
code[i] = new StringBuffer();
while (!tem.empty()) {
code[i].append(tem.pop());
}
}
return code;
}
public static StringBuffer getString (Note[] note, String code) {
StringBuffer str = new StringBuffer();
int n = note.length;
int p = n - 1;
for (int i = 0; i < code.length();i ++) {
char ch = code.charAt(i);
if (ch == '0') {
p = note[p].lChild;
} else {
p = note[p].rChild;
}
if (note[p].lChild == -1) {
str.append(note[p].ch);
p = n - 1;
}
}
return str;
}
public static void mid (Note[] note, int t) { //中序遍歷
if (t == -1) return;
System.out.print(note[t].weight + ",");
mid(note,note[t].lChild);
mid(note,note[t].rChild);
}
public static void main(String[] args) {
int n = 5; //葉子節點的數量
char[] ch = new char[]{'a','b','c','d','e'}; //求編碼的字符
int[] weight = new int[]{5,15,40,30,10}; //每個字符的權值
Note[] note = new Note[2 * n - 1]; //採用順序存儲結構
for (int i = 0;i < n;i ++) { //建立每一個葉子節點對象,並把每一個葉子節點看作一棵樹
note[i] = new Note(ch[i],weight[i],-1,-1,-1);
}
for (int i = n; i < 2 * n - 1; i ++) {
int[] min = min(note, i); //選出權值最小的兩個跟節點
merge(note,min[0],min[1],i); //合併兩個權值最小的樹
}
mid(note,2 * n - 2); //中序遍歷,輸出來看看
System.out.println();
StringBuffer[] code = getCode(note); //獲取赫夫曼編碼
for (int i = 0;i < n; i ++) {
System.out.println(ch[i] + ":" + code[i]);
}
StringBuffer string = getString(note, "11111001101110");
System.out.println(string);
}
}
class Note {
int weight;
char ch;
int lChild, rChild;
int parent;
public Note(int weight, int lChild, int rChild, int parent) {
this.weight = weight;
this.lChild = lChild;
this.rChild = rChild;
this.parent = parent;
}
public Note(char ch, int weight, int lChild, int rChild, int parent) {
this.ch = ch;
this.weight = weight;
this.lChild = lChild;
this.rChild = rChild;
this.parent = parent;
}
}
輸出結果: