相关介绍:

 树形结构除了应用于查找和排序等操作时能调高效率,它在信息通讯领域也有着广泛的应用。哈弗曼(Huffman)树就是一种在编码技术方面得到广泛应用的二叉树,它同时也是一种最优二叉树。

哈弗曼树相关的的基本概念:

 为了给出哈弗曼树的定义,从以下几个基本概念出发并进行描述。

  1. 节点间的路径和节点的路径长度:所谓节点间的路径是指一个节点到另一个节点所经历的节点和分支序列。节点的路径长度是指从根节点到该节点间的路径上的分支数目。

  2. 节点的权和节点的带权路径:在实际应用中,人们往往会给树中的每一个节点赋予一个具有某种实际意义的数值,这个数值称为节点的权值。节点的带权路径长度就是该节点的路径长度与该节点的权值的乘积。

  3. 树的带权路径长度:树的带权路径长度就是树中所有叶节点的带权路径长度之和,通常记为:\(WPL=\sum_{i=1}^{n}W_{i} \times L_{i}\)其中,n为叶节点的个数,\(W_{i}\)为第i个叶节点的权值,\(L_{i}\)为第i个叶节点的路径长度

  4. 最优二叉树:给定n个权值并作为n个叶节点按一定规则构造一棵二叉树,使得其带权路径长度达到最小值,则这棵二叉树被称为最优二叉树。下图展示了具有不同带权路径长度的二叉树,其中,第二棵树为最优二叉树

哈弗曼树和哈弗曼编码的构造方法

 哈弗曼树的构造步骤如下所示:

 假设n个叶节点的权值分别为{w1,w2,...,wn},则

  1. 由已知给定的n个权值{w1,w2,w3,...,wn},构造一个由n棵二叉树所构成的森林F={T1,,T2,T3,...,Tn},其中每一棵二叉树只有一个根节点,并且根节点的权值分别为w1,w2,....,wn

  2. 在二叉树森林F中选取根节点的权值最小和次小的两棵二叉树,分别把它们作为左子树和右子树去构造一棵新二叉树,新二叉树的根节点权值为其左、右子树根节点的权值之和

  3. 作为新二叉树的左右子树的两棵二叉树从森林F中删除。将新产生的二叉树加入到森林F中

  4. 重复步骤2和步骤3,直到森林中只剩下一棵二叉树为止,则这棵二叉树就是所构成的哈弗曼树

下图展示了哈弗曼树的构造过程:

哈弗曼树构造过程的代码实现

 以下其代码演示了哈弗曼树的构造实现其中,测试代码所用的图如下所示:

相关代码:

package all_in_tree;

import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue; /**
* 该类用于演示哈弗曼树的构造过程
* @author 学徒
*
*/
public class Huffman
{
//哈弗曼树的根节点
private HuffmanNode root;
//一个优先级队列,确保每次取出的均为节点中其权值最小的节点
private Queue<HuffmanNode> q;
/**
* 用于初始化,其优先队列
*/
public Huffman()
{
Comparator<HuffmanNode> cmp=new Comparator<HuffmanNode>()
{
@Override
public int compare(HuffmanNode obj1,HuffmanNode obj2)
{
int obj1Number=obj1.weight;
int obj2Number=obj2.weight;
if(obj1Number>obj2Number)
return 1;
else if(obj1Number<obj2Number)
return -1;
else
return 0;
}
};
q=new PriorityQueue<HuffmanNode>(11,cmp);
}
/**
* 用于添加节点到优先队列中,进行哈弗曼树的构造
* @param node
*/
public void addHuffmanNode(HuffmanNode node)
{
q.add(node);
}
/**
* 用于构造哈弗曼树
*/
public HuffmanNode createHuffmanTree()
{
while(!q.isEmpty()&&q.size()>=2)
{
HuffmanNode node1=q.poll();
HuffmanNode node2=q.poll();
HuffmanNode newNode=new HuffmanNode();
newNode.weight=node1.weight+node2.weight;
newNode.left=node1;
newNode.right=node2;
q.add(newNode);
}
if(!q.isEmpty())
this.root=q.poll();
return this.root;
}
/**
* 用于测试相关的代码
*/
public static void main(String[] args)
{
Huffman tree=new Huffman();
for(int i=0;i<5;i++)
{
tree.addHuffmanNode(new HuffmanNode((char)('A'+i),i+1));
}
HuffmanNode root=tree.createHuffmanTree();
System.out.println("其最高顶点的权值"+root.weight);
//对该哈弗曼树进行层次遍历
Queue<HuffmanNode> q=new LinkedList<HuffmanNode>();
q.add(root);
while(!q.isEmpty())
{
HuffmanNode node=q.poll();
System.out.print(node.weight+"\t");
if(node.left!=null)
q.add(node.left);
if(node.right!=null)
q.add(node.right);
}
}
}
/**
* 用于创建哈弗曼树的节点类的描述
* @author 学徒
*
*/
class HuffmanNode
{
//用于存放相关的数据
Object data;
//用于记录该节点的权
int weight;
//该节点的左孩子
HuffmanNode left;
//该节点的右孩子
HuffmanNode right;
public HuffmanNode()
{
}
public HuffmanNode(Object data,int weight)
{
this.data=data;
this.weight=weight;
}
} 运行结果: 其最高顶点的权值15
15 6 9 3 3 4 5 1 2

回到目录|·(工)·)

K:哈弗曼树的更多相关文章

  1. HDU2527:Safe Or Unsafe(哈弗曼树)

    Problem Description Javac++ 一天在看计算机的书籍的时候,看到了一个有趣的东西!每一串字符都可以被编码成一些数字来储存信息,但是不同的编码方式得到的储存空间是不一样的!并且当 ...

  2. SLT 优先队列 哈弗曼树最小带权路径

    与普通的队列不同,普通的队列是先进先出的,而优先队列出队的顺序不是先进先出,而是大(或者小)元素先出队,需要#include <queue> 成员函数 成员函数 作用 empty() 判断 ...

  3. java实现哈弗曼树

    O(∩_∩)O~~ 概述 我想学过数据结构的小伙伴一定都认识哈弗曼,这位大神发明了大名鼎鼎的“最优二叉树”,为了纪念他呢,我们称之为“哈弗曼树”.哈弗曼树可以用于哈弗曼编码,编码的话学问可就大了,比如 ...

  4. 哈弗曼树的理解和实现(Java)

    哈弗曼树概述 哈弗曼树又称最优树,是一种带权路径长度最短的树,在实际中有广泛的用途.哈弗曼树的定义,涉及路径.路径长度.权等概念.哈弗曼树可以用于哈弗曼编码,用于压缩,用于密码学等. 哈弗曼树的一些定 ...

  5. PKU 1521 Entropy(简单哈弗曼树_水过)

    题目大意:原题链接 给你一个字符串,首先是计算出一个按正常编码的编码长度,其次是计算出一个用霍夫曼编码的编码长度,最后求正常编码的长度除以霍夫曼编码长度的比值,保留一位小数. 解题思路:需要知道 1. ...

  6. POJ 3253 Fence Repair(简单哈弗曼树_水过)

    题目大意:原题链接 锯木板,锯木板的长度就是花费.比如你要锯成长度为8 5 8的木板,最简单的方式是把21的木板割成13,8,花费21,再把13割成5,8,花费13,共计34,当然也可以先割成16,5 ...

  7. Python 数据结构与算法 —— 哈弗曼树

    1. 从扩充二叉树到哈弗曼树 扩充二叉树:对二叉树 T,加入足够多的新叶节点(而不是任意),使 T 的原有结点都变成度数为 2 的分支节点,得到的二叉树称为 T 的扩充二叉树. 对于扩充二叉树而言, ...

  8. java实现哈弗曼树和哈夫曼树压缩

    本篇博文将介绍什么是哈夫曼树,并且如何在java语言中构建一棵哈夫曼树,怎么利用哈夫曼树实现对文件的压缩和解压.首先,先来了解下什么哈夫曼树. 一.哈夫曼树 哈夫曼树属于二叉树,即树的结点最多拥有2个 ...

  9. POJ 3253 Fence Repair【哈弗曼树/贪心/优先队列】

    Fence Repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 53645   Accepted: 17670 De ...

随机推荐

  1. Intellij IDEA安装golang插件

    原文作者:Jianan - qinxiandiqi@foxmail.com 原文地址:http://blog.csdn.net/qinxiandiqi/article/details/50319953 ...

  2. 兔子-ps抠图

    介绍2种方法:1.用高速选择工具 2.用铅笔工具 1.高速选择后.ctrl+c复制,新建空白图片,粘贴进去 2.用钢笔工具在图像的边缘定出若二个点,确定完毕之后按crtl+回车键选择.然后复制,新建空 ...

  3. jQuery:deferred [转]

    jQuery的开发速度很快,几乎每半年一个大版本,每两个月一个小版本. 每个版本都会引入一些新功能.今天我想介绍的,就是从jQuery 1.5.0版本开始引入的一个新功能----deferred对象. ...

  4. NanUI文档 - 开始使用NanUI

    NanUI文档目录 NanUI简介 开始使用NanUI 打包并使用内嵌式的HTML/CSS/JS资源 使用网页来设计整个窗口 如何实现C#与Javascript相互掉用(待更新...) 如何处理Nan ...

  5. Android项目实战(三十八):2017最新 将AndroidLibrary提交到JCenter仓库(图文教程)

    我们经常使用github上的开源项目,使用步骤也很简单 比如: compile 'acffo.xqx.xwaveviewlib:maven:1.0.0' 这里就学习一下如何将自己的类库做出这种可以供他 ...

  6. Eclipse 问题整理

    新建servlet报错,提示找不到javax.servlet包 解决的方法:把tomcat安装包里的lib目录下的servlet-api.jar拷贝一份到工程文件夹下的web目录下的WEB-INF目录 ...

  7. sharepreference使用教程

    1.应用 SharePreference主要用于保存一些数据,比如用户登录后的user_id,user_mobile,这样就可以做自动登录了,每次判断SharePreference中有没有数据,有的话 ...

  8. 为了CET-4!(二)

    directions: For this part,you are allowed 30 minutes to write an eassay.Suppose there are two option ...

  9. Winccflexable触摸屏的报警

    1.报警的分类 2.自定义报警分类 3.报警组成 4.Winccflexable中预定义的报警类别 5.报警的确认 6.WinccFlexable报警的显示 1)报警视图 2)报警窗口 3).报警指示 ...

  10. python的属性(property)使用

    在面向对象编程的时候,我们定义一个Person类 class Person: def __init__(self): self.age = 22 这样写法能够方便的访问属性age, p = Perso ...