对某一字符串的最短二进制编码称为赫夫曼编码。
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;
}
}
输出结果: