哈夫曼树的介绍 ---java实现

Posted llguanli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈夫曼树的介绍 ---java实现相关的知识,希望对你有一定的参考价值。

一、     什么是哈夫曼树

是一种带权路径长度最短的二叉树,也称最优二叉树

带权路径长度:WPL=(W1*L1+W2*L2+W3*L3+...+ Wn*Ln)

N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树。对应的叶结点的路径长度为Li(i=1,2,...n)

 

二、     建立哈夫曼树

已知的一组叶子的权值w1,w2,w3……wn; 
首先把 个叶子结点看做 棵树(仅有一个结点的二叉树)。把它们看做一个森林。

 
在森林中把权值最小和次小的两棵树合并成一棵树。该树根结点的权值是两棵子树权值之和。

这时森林中还有 n-1 棵树。

 
反复第步直到森林中仅仅有一棵为止。此树就是哈夫曼树。

现给一组 (n=4) 详细的权值: 2    ,下边是构造详细过程:

 

n 个叶子构成的哈夫曼树其带权路径长度是唯一的。但树形是不唯一的。由于将森林中两棵权值最小和次小的子棵合并时,哪棵做左子树,哪棵做右子树并不严格限制。

 

三、     哈夫曼树的应用


a)       哈夫曼编码

 利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每一个叶子节点都有一条路径,对路径上的各分支约定指向左子树的分支表示”0”码,指向右子树的分支表示“1”码。取每条路径上的“0”或“1”的序列作为各个叶子节点相应的字符编码,即是哈夫曼编码。

当中A,B,C,D相应的哈夫曼编码分别为:111。10,110。0


b)      二路归并排序

如果如今有n个已经排序的文件{d1,d2,….dn}。每一个文件包括的记录个数相应是{w1,w2,w3…..wn};能够採用两两合并的方法,把所有文件的记录合并到一个大文件里,使得这个文件里的记录所有排序。

              问:採用什么合并次序才干使移动个数最少?

              答:依照哈夫曼树的结构从外部结点到根节点逐层进行合并,一定是一种最佳的合并顺序。

 



四、      哈夫曼树的代码实现

用java实现的哈夫曼树
public class Huffman {
	public static void main(String[] args){
		Huffman huffman = new Huffman();
		int[] a = {2,3,5,7,11,13,17,19,23,29,31,37,41};
		System.out.println(a.length);
		HfTree tree = huffman.createHfTree(a.length , a);
		System.out.println("ht  ww  parent  lchild  rchild ");
		for(int i=0;i<tree.node.length;i++){
			System.out.println(i +" "+ tree.node[i].ww +" "+ tree.node[i].parent +" "+ tree.node[i].lchild +" "+ tree.node[i].rchild);
		}
		
	}
	
	private static int MAXINT=10000;
	public HfTree createHfTree(int m , int a[]){
		HfTree hfTree = new HfTree(m);
		/*初始化哈夫曼树*/
		for(int i=0;i<2*m-1;i++){
			hfTree.node[i].lchild = -1;
			hfTree.node[i].rchild = -1;
			hfTree.node[i].parent = -1;
			if(i<m){
				hfTree.node[i].ww = a[i];
			}
		}
		/*開始生成哈夫曼树*/
		for(int i=0; i<m-1;i++){
			int x1 = 0;
			int x2 = 0;
			int m1 = MAXINT;
			int m2 = MAXINT;
			for(int j=0; j<m+i;j++){
				if(hfTree.node[j].ww < m1 && hfTree.node[j].parent == -1){
					m2 = m1;
					x2 = x1;
					m1 = hfTree.node[j].ww;
					x1 = j;
				}
				else if(hfTree.node[j].ww < m2 && hfTree.node[j].parent == -1){
					m2 = hfTree.node[j].ww;
					x2 = j;
				}
			}
			hfTree.node[x1].parent = m+i;
			hfTree.node[x2].parent = m+i;
			hfTree.node[m+i].ww = m1+m2;
			hfTree.node[m+i].lchild = x1;
			hfTree.node[m+i].rchild = x2;
		}
		hfTree.root = 2*m-2;
		return hfTree;
	}
	
	
	
}


class HfNode{
	public int ww;
	public int parent;
	public int lchild;
	public int rchild;
	
}
 
class HfTree{
	  public HfNode[] node;
	  public int root;
	  public int m;
	 
	 HfTree(int m){
		 this.m = m;
		 this.node = new HfNode[2*m-1];
		//初始化对象数组是必须每一个对象都创建
		 for(int i=0;i<2*m-1;i++){
			 node[i] = new HfNode(); 
		 }
	 }
	

		
 }
 


以上是关于哈夫曼树的介绍 ---java实现的主要内容,如果未能解决你的问题,请参考以下文章

哈夫曼树(最优二叉树)详解与构造

数据结构——哈夫曼树

使用优先队列构建赫夫曼树

数据结构与算法-赫夫曼树

哈夫曼树的基础知识

求哈夫曼树的编码