哈夫曼树(霍夫曼树)-详解
在了解哈佛曼树前,需要先了解,何为权值,何为路径,以及权值计算。
何为权值?我们看下百度百科的解释。
by:百度百科
在数学领域,权值指加权平均数中的每个数的频数,也称为权数或权重。
计算机领域中(数据结构)
权值就是定义的路径上面的值。可以这样理解为结点间的距离。通常指字符对应的二进制编码出现的概率。
至于[哈夫曼树]中的权值可以理解为:权值大表明出现概率大!
一个结点的权值实际上就是这个结点子树在整个树中所占的比例.
abcd四个[叶子结点]的权值为7,5,2,4, 这个7,5,2,4是根据实际情况得到的,比如说从一段文本中统计出abcd四个字母出现的次数分别为7,5,2,4. 说a结点的权值为7,意思是说a结点在系统中占有7这个份量。实际上也可以化为百分比来表示,但反而麻烦,实际上是一样的。
何为路径?
连接两个节点的线就是路径。
何为路径长度?
从顶点到 1,其需要经过 a 、b 路径。那么路径长度就为2
何为树的路径长度?
从树的顶点,到各个节点的路径长度总和,即为树的路径长度。
何为结点的带权路径长度?
结点权即为本身数值,而结点的带权路径长度为从树的订单到结点的路径长度与结点的权 数值乘积。
公式: 结点的带权路径长度 = 结点的路径长度 * 结点的带权值
例:上图,从顶点到对应结点,那么它的带权路径长度为 2 x 100 = 200
何为树的带权路径长度(WPL)?
树的带权路径长度为结点的带权路径长度之和。可参考上图。
哈夫曼树(霍夫曼树)介绍
by: 百度百科
给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。
一个二叉树的带权路径长度(WPL)最小,才能为哈夫曼树。而要使得WPL最小,则需要结点权值最大越靠近顶点,而结点权值越小离顶点越远。
以下为图示的简单例子:
package com.base.data.tree;
/**
* 创建一个结点,包含权重信息 * @param <E>
*/
public class HuffTreeNode<E> {
E data;
double weight;
HuffTreeNode leftNode;
HuffTreeNode rightNode;
public HuffTreeNode(E data,double weight) {
this.data = data;
this.weight = weight;
}
public HuffTreeNode(E data, double weight, HuffTreeNode leftNode, HuffTreeNode rightNode) {
this.data = data;
this.weight = weight;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
}
package com.base.data.tree;
import java.util.*;
public class HuffTree {
/**
* 创建哈夫曼树
* @param huffTreeNodeList {@link HuffTreeNode}
* @return 返回树
*/
public HuffTreeNode createHuffTree(List<HuffTreeNode> huffTreeNodeList){
while(huffTreeNodeList.size() > 1){
//排序
sortHuffTrees(huffTreeNodeList);
int size = huffTreeNodeList.size();
//从尾部开始循环
HuffTreeNode leftNode = huffTreeNodeList.get(size-1);
HuffTreeNode rightNode = huffTreeNodeList.get(size-2);
//创建父结点
HuffTreeNode parentNode = new HuffTreeNode(null,leftNode.weight+rightNode.weight);
parentNode.leftNode = leftNode;
parentNode.rightNode = rightNode;
huffTreeNodeList.remove(size-1);
huffTreeNodeList.remove(size-2);
huffTreeNodeList.add(parentNode);
}
return huffTreeNodeList.get(0);
}
/**
* 冒泡排序 结点的权重信息 从大到小
* @param huffTreeNodeList
*/
public void sortHuffTrees(List<HuffTreeNode> huffTreeNodeList){
int i = huffTreeNodeList.size()-1;
while (i > 0){
int post = 0;
for (int i1 = 0; i1 < i; i1++) {
if(huffTreeNodeList.get(i1).weight < huffTreeNodeList.get(i1+1).weight){
post = i1;
HuffTreeNode temp = huffTreeNodeList.get(i1+1);
huffTreeNodeList.set(i1+1,huffTreeNodeList.get(i1));
huffTreeNodeList.set(i1,temp);
}
}
i = post;
}
}
public void printNode(HuffTreeNode huffTreeNode){
System.out.println(huffTreeNode.weight);
if(huffTreeNode.leftNode != null){
System.out.println(huffTreeNode.leftNode.weight);
printNode(huffTreeNode.leftNode);
}
if(huffTreeNode.rightNode != null){
System.out.println(huffTreeNode.rightNode.weight);
printNode(huffTreeNode.rightNode);
}
}
public static void main(String[] args) {
HuffTree huffTree = new HuffTree();
List<HuffTreeNode> huffTreeNodeList = new ArrayList<>();
for(int i=0;i<1000;i++){
Random random = new Random();
double randomDouble = random.nextInt(100000);
huffTreeNodeList.add(new HuffTreeNode("A结点"+i, randomDouble));
}
huffTree.createHuffTree(huffTreeNodeList);
huffTree.printNode(huffTreeNodeList.get(0));
}
}