相关介绍:

 树形结构除了应用于查找和排序等操作时能调高效率,它在信息通讯领域也有着广泛的应用。哈弗曼(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. php之str_replace具体解释

    str_replace (PHP 4, PHP 5) str_replace - Replace all occurrences of the search string with the repla ...

  2. 前端优化之动画为什么要尽量用css3代替js

    导致JavaScript效率低的两大原因:操作DOM和使用页面动画.通常我们会通过频繁的操作 DOM的CSS来实现视觉上的动画效果,导致js效率低的两个因素都包括在内了在频繁的操作DOM和CSS时,浏 ...

  3. 大数据学习(5)MapReduce切片(Split)和分区(Partitioner)

    MapReduce中,分片.分区.排序和分组(Group)的关系图: 分片大小 对于HDFS中存储的一个文件,要进行Map处理前,需要将它切分成多个块,才能分配给不同的MapTask去执行. 分片的数 ...

  4. java中md5加密方法

    package com.func; import java.io.UnsupportedEncodingException;import java.math.BigInteger;import jav ...

  5. 《程序设计实践》【PDF】下载

    <程序设计实践>[PDF]下载链接: https://u253469.ctfile.com/fs/253469-231196319 内容简介 本书从排错.测试.性能.可移植性.设计.界面. ...

  6. 《大型网站系统与JAVA中间件实践》【PDF】下载

    <大型网站系统与JAVA中间件实践>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062557 内容简介 到底是本什么书,拥有这样 ...

  7. 【二十四】使用mysqli扩展类批量执行多条sql语句

    批量处理多个sql语句 <?php //批量执行多个dml语句 // $mysqli=new mysqli("localhost","root",&quo ...

  8. 从初识Maven到使用Maven进行依赖管理和项目构建

    前些天就安装了Maven,以备自己以后整合项目用,尤其是我们的ssh,ssm项目.想必好多人在开始的时候并不清楚Maven是什么,它能够帮助我们干什么. 所以在学习Maven之前我们一定要知道它是什么 ...

  9. ReactNative 基础学习

    安卓Back键的处理·基本+高级篇 http://bbs.reactnative.cn/topic/480/%E5%AE%89%E5%8D%93back%E9%94%AE%E7%9A%84%E5%A4 ...

  10. Office 365实现单点登录系列(1)—域环境搭建

    Hello 小伙伴们, 2018新年快乐,作为2018年首篇文章,怎么能不给大家带来点干货呢?这篇文章其实我9月底的时候已经在MSDN上发布过了,为表诚意,我更新了这篇文章,并把它组成了一个系列,2. ...