首页 > 代码库 > 哈夫曼树
哈夫曼树
一、 什么是哈夫曼树
是一种带权路径长度最短的二叉树,也称最优二叉树
带权路径长度: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 个叶子结点看做 n 棵树(仅有一个结点的二叉树),把它们看做一个森林。
②在森林中把权值最小和次小的两棵树合并成一棵树,该树根结点的权值是两棵子树权值之和。这时森林中还有 n-1 棵树。
③重复第②步直到森林中只有一棵为止,此树就是哈夫曼树。
现给一组 (n=4) 具体的权值: 2 , 4 , 5 , 8 ,下边是构造具体过程:
n 个叶子构成的哈夫曼树其带权路径长度是唯一的,但树形是不唯一的。因为将森林中两棵权值最小和次小的子棵合并时,哪棵做左子树,哪棵做右子树并不严格限制。
三、 哈夫曼树的应用
a) 哈夫曼编码
利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子节点都有一条路径,对路径上的各分支约定指向左子树的分支表示”0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为各个叶子节点对应的字符编码,即是哈夫曼编码。
其中A,B,C,D对应的哈夫曼编码分别为:111,10,110,0
b) 二路归并排序
假设现在有n个已经排序的文件{d1,d2,….dn},每个文件包含的记录个数对应是{w1,w2,w3…..wn};可以采用两两合并的方法,把所有文件的记录合并到一个大文件中,使得这个文件中的记录全部排序。
问:采用什么合并次序才能使移动个数最少?
答:按照哈夫曼树的结构从外部结点到根节点逐层进行合并,一定是一种最佳的合并顺序。
四、 哈夫曼树的代码实现
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(); } } }