相关介绍:

 树形结构除了应用于查找和排序等操作时能调高效率,它在信息通讯领域也有着广泛的应用。哈弗曼(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. Android酷炫有用的开源框架

    一.代码库 1.from  代码家 整理比較好的源代码连接 一.兼容类库 ActionBarSherlock : Action Bar是Android 3.0后才開始支持的,ActionBarSher ...

  2. Android学习笔记(27):日历视图Calendar

    日历视图CalendarView可用于显示和选择日期. 能够调用setOnDateChangedListener()方法绑定事件监听器. 经常使用XML属性和相关方法: XML属性 相关方法 说明 a ...

  3. IIS 服务或万维网公布服务,或者依赖这 服务可能在启动期间错误发生或者已禁用

    作者:jiankunking 出处:http://blog.csdn.net/jiankunking 详细错误信息例如以下: 解决方式: 在服务中禁用下面3个服务自己主动启动: Net.Msmq Li ...

  4. 【Jquery系列】prop和attr区别

    问题描述 由于prop(property的缩写)和attr(attribute的缩写)翻译成汉语,均有“特性.属性”等意思的原因,导致大家容易混淆分不清,本篇文章将试图从英文含义,中文含义和Jquer ...

  5. 四.RabbitMQ之发布/订阅(Publish/Subscribe)

    一.基础知识点 在上述章节中,我们理解的RabbitMQ是基于如下这种模式运作的. 而事实上,这只是我们简单化了的模型的结果,真正的模型应该是这样的. P:Producer 生产者,生产消息,把它放进 ...

  6. 自学Zabbix3.9.1-模板Templates-创建

    自学Zabbix3.9.1-模板Templates-创建 1. 模板介绍 模板是一组可以方便地应用于多个主机的实体. 实体可能是: 项目 触发器 图 应用程序 屏幕(因为Zabbix 2.0) 低层次 ...

  7. MQTT 设计原则

    MQTT 设计原则 简单. 没有杂七杂八的花俏功能,作为一个基础组件构建实用的系统,易于实现. "发布/订阅"消息传递方式. 随时接入随时发布.接收消息,无需太多其他"事 ...

  8. web前端学习就这9个阶段,你属于哪个阶段?

    第一阶段:HTML+CSS: HTML进阶.CSS进阶.div+css布局.HTML+css整站开发. JavaScript基础:Js基础教程.js内置对象常用方法.常见DOM树操作大全.ECMAsc ...

  9. Laravel学习笔记(三)--在CentOS上配置Laravel

    在Laravel框架上开发了几天,不得不说,确实比较优雅,处理问题逻辑比较清楚.     今天打算在CentOS 7上配置一个Laravel,之前都是在本机上开发,打算实际配置一下.     1)系统 ...

  10. .NET开发一个微信跳一跳辅助程序

    昨天微信更新了,出现了一个小游戏"跳一跳",玩了一下 赶紧还蛮有意思的 但纯粹是拼手感的,玩了好久,终于搞了个135分拿了个第一名,没想到过一会就被朋友刷下去了,最高的也就200来 ...