哈弗曼树的实现
必須提供權值才能構建出一棵哈弗曼樹,因為哈弗曼樹的定義為帶權路徑長度最小的二叉樹。?
樹的帶權路徑長度為所有葉子節點的帶權路徑長度。?
節點的帶權路徑長度為該節點到樹的路徑長度乘以節點權值。?
哈希曼樹最主要的應用是產生哈希曼編碼。?
為特點元素設計哈希曼編碼要求二進制編碼盡可能的短,并且任意一個字符的編碼不是另外一個?
字符的編碼的前綴。
package com.algorithm;
/**
?* 最優二叉樹(哈夫曼樹)
?* 根據元素的權值構建哈夫曼樹,并設計其哈弗曼編碼
?* 使用數組存儲節點
?*/
public class Hufuman {
private int[] weights; //存儲權值
private int n;
private TreeNode[] nodes; //存儲節點的數組
private int m; //數組長度
class TreeNode{
int weight; //權值
int Parent; //父節點的下標
int lchild; //左孩子下標
int rchild; //右孩子下標
public TreeNode(int weight,int parent,int lchild,int rchild){
this.weight = weight;
this.Parent = parent;
this.lchild = lchild;
this.rchild = rchild;
}
}
public Hufuman(){
}
public Hufuman(int[] w){
this.weights = w;
int n = w.length;
if(n <= 1){
throw new IllegalArgumentException();
}
this.n = n;
init();
}
/**
* 初始化節點數組
*/
private void init(){
? ?m = 2*n - 1;
nodes = new TreeNode[m];
int i;
for(i = 0;i < n ;++i){
nodes[i] = new TreeNode(weights[i], -1, -1, -1); //-1表示無父或孩子節點
}
for(;i < m;++i){
nodes[i] = new TreeNode(-1, -1, -1, -1);
}
}
/**
* 根據權值構建哈夫曼樹
*/
public void create(){
int min,secmin;
for(int i = n;i < m;++i){
int[] mins = select(i-1);
min = mins[0];
secmin = mins[1];
nodes[min].Parent = i ;
nodes[secmin].Parent = i;
nodes[i].lchild = min;
nodes[i].rchild = secmin;
nodes[i].weight = nodes[min].weight + nodes[secmin].weight;
}
}
/**
* 從葉子節點逆向求每個字符的哈弗曼編碼
*/
public String[] hufumanCoding(){
String[] codes = new String[n];
StringBuilder sb ;
for(int i=0;i<n;++i){ //i到n都是葉子節點
sb = new StringBuilder();
for(int c=i,p=nodes[i].Parent;p!=-1;c=p,p=nodes[p].Parent){
if(nodes[p].lchild == c)
sb.append('0'); //左分支表示字符'0'
else
sb.append('1'); //右分支表示字符'1'
}
codes[i] = sb.reverse().toString();
}
return codes;
}
/**
* 取weight最小的兩個節點
*/
private int[] select(int last){
int min=0; //最小值下標
int secmin=0; //次小值下標
int i;
for(i=0;i<=last;++i){
if(nodes[i].Parent==-1){
min = i;
break;
}
}
for(i=i+1;i<=last;++i){
if(nodes[i].Parent==-1){
secmin = i;
break;
}
}
int temp;
if(nodes[min].weight > nodes[secmin].weight){
temp = min;
min = secmin;
secmin = temp;
}
for(i=i+1;i<=last;++i){
if(nodes[i].Parent!=-1)continue;
if(nodes[i].weight < nodes[min].weight){
secmin = min;
min = i;
}else{
if(nodes[i].weight < nodes[secmin].weight)
secmin = i;
}
}
int[] minValues = {min,secmin};
return minValues;
}
public void printTree(){
System.out.println(" ? | weight | parent | lchild | rchild |");
for(int i=0;i<m;i++){
System.out.print(i+" ?| ? "+nodes[i].weight+" ? | ? "+nodes[i].Parent+" ? | ? "+nodes[i].lchild+" ? | ? "+nodes[i].rchild+" ? |");
System.out.println();
}
}
public static void main(String[] args) {
int[] w = {5,29,7,8,14,23,3,11};
Hufuman t = new Hufuman(w);
t.create();
t.printTree();
String[] str = t.hufumanCoding();
for(String s:str){
System.out.println(s);
}
}
}
轉自:http://zhouyunan2010.iteye.com/blog/1184303
總結
- 上一篇: 二叉排序树的实现——java
- 下一篇: java中的排序算法——简单选择排序,树