哈夫曼树详解

article/2025/8/25 13:32:56

一、哈夫曼树的介绍

Huffman Tree,中文名是哈夫曼树或霍夫曼树,它是最优二叉树。

定义:给定n个权值作为n个叶子结点,构造一棵二叉树,若树的带权路径长度达到最小,则这棵树被称为哈夫曼树。 这个定义里面涉及到了几个陌生的概念,下面就是一颗哈夫曼树,我们来看图解答。

(1) 路径和路径长度

定义:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。 例子:100和80的路径长度是1,50和30的路径长度是2,20和10的路径长度是3。

(2) 结点的权及带权路径长度

定义:若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。 例子:节点20的路径长度是3,它的带权路径长度= 路径长度 * 权 = 3 * 20 = 60。

(3) 树的带权路径长度

定义:树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。 例子:示例中,树的WPL= 1*100 + 2*50 + 3*20 + 3*10 = 100 + 100 + 60 + 30 = 290。

比较下面两棵树

上面的两棵树都是以{10, 20, 50, 100}为叶子节点的树。

左边的树WPL=2*10 + 2*20 + 2*50 + 2*100 = 360 右边的树WPL=290

左边的树WPL > 右边的树的WPL。你也可以计算除上面两种示例之外的情况,但实际上右边的树就是{10,20,50,100}对应的哈夫曼树。至此,应该对哈夫曼树的概念有了一定的了解了,下面看看如何去构造一棵哈夫曼树。

二、哈夫曼树的图文解析

假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,哈夫曼树的构造规则为:

1. 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点); 2. 在森林中选出根结点的权值最小的两棵树进行合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和; 3. 从森林中删除选取的两棵树,并将新树加入森林; 4. 重复(02)、(03)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。

以{5,6,7,8,15}为例,来构造一棵哈夫曼树。

第1步:创建森林,森林包括5棵树,这5棵树的权值分别是5,6,7,8,15。 第2步:在森林中,选择根节点权值最小的两棵树(5和6)来进行合并,将它们作为一颗新树的左右孩子(谁左谁右无关紧要,这里,我们选择较小的作为左孩子),并且新树的权值是左右孩子的权值之和。即,新树的权值是11。 然后,将"树5"和"树6"从森林中删除,并将新的树(树11)添加到森林中。 第3步:在森林中,选择根节点权值最小的两棵树(7和8)来进行合并。得到的新树的权值是15。 然后,将"树7"和"树8"从森林中删除,并将新的树(树15)添加到森林中。 第4步:在森林中,选择根节点权值最小的两棵树(11和15)来进行合并。得到的新树的权值是26。 然后,将"树11"和"树15"从森林中删除,并将新的树(树26)添加到森林中。 第5步:在森林中,选择根节点权值最小的两棵树(15和26)来进行合并。得到的新树的权值是41。 然后,将"树15"和"树26"从森林中删除,并将新的树(树41)添加到森林中。 此时,森林中只有一棵树(树41)。这棵树就是我们需要的哈夫曼树!

三、哈夫曼树的基本操作

哈夫曼树的重点是如何构造哈夫曼树。本文构造哈夫曼时,用到了以前介绍过的"(二叉堆)最小堆"。下面对哈夫曼树进行讲解。

1. 基本定义

[html]

view plain

copy

print

HuffmanNode是哈夫曼树的节点类。

[html]

view plain

copy

print

Huffman是哈夫曼树对应的类,它包含了哈夫曼树的根节点和哈夫曼树的相关操作。

2. 构造哈夫曼树

[html]

view plain

copy

print

首先创建最小堆,然后进入for循环。

每次循环时:

(1) 首先,将最小堆中的最小节点拷贝一份并赋值给left,然后重塑最小堆(将最小节点和后面的节点交换位置,接着将"交换位置后的最小节点"之前的全部元素重新构造成最小堆); (2) 接着,再将最小堆中的最小节点拷贝一份并将其赋值right,然后再次重塑最小堆; (3) 然后,新建节点parent,并将它作为left和right的父节点; (4) 接着,将parent的数据复制给最小堆中的指定节点。

四、哈夫曼树的完整源码

1. 哈夫曼树的节点类(HuffmanNode.java)

[html]

view plain

copy

print

2. 哈夫曼树的实现文件(Huffman.java)

[html]

view plain

copy

print

3. 哈夫曼树对应的最小堆(MinHeap.java)

[html]

view plain

copy

print

4. 哈夫曼树的测试程序(HuffmanTest.java)

[html]

view plain

copy

print

五个字符:a,b,c,d,e,它们出现的的频率为8,14,10,4,18构造相应的哈夫曼树,求出每个字符的哈夫曼编码:

哈夫曼树:

54

/        \

22             32

/      \         /    \

c10  12   b14  e18

/   \

d4    a8哈夫曼编码:

a:011  b:10  c:00 d:010 e:11

今天做题的时候,遇到了一个关于哈夫曼树的题,由于一直不是很明白哈夫曼树的构造过程,所以找了很多资料都不是特别清楚的,直到我遇到了这篇文章,哈哈,在此分享给大家哦!

注意:哈夫曼树并不唯一,但带权路径长度一定是相同的。

(1)8个结点的权值大小如下:

(2)从19,21,2,3,6,7,10,32中选择两个权小结点。选中2,3。同时算出这两个结点的和5。

(3)从19,21,6,7,10,32,5中选出两个权小结点。选中5,6。同时计算出它们的和11。

(4)从19,21,7,10,32,11中选出两个权小结点。选中7,10。同时计算出它们的和17。 (BTW:这时选出的两个数字都不是已经构造好的二叉树里面的结点,所以要另外开一棵二叉树;或者说,如果两个数的和正好是下一步的两个最小数的其中的一个,那么这个树直接往上生长就可以了,如果这两个数的和比较大,不是下一步的两个最小数的其中一个,那么就并列生长。)

(4)从19,21,7,10,32,11中选出两个权小结点。选中7,10。同时计算出它们的和17。

(BTW:这时选出的

两个数字都不是已经构造好的二叉树里面的结点

,所以要另外开一棵二叉树;或者说,

如果两个数的和正好是下一步的两个最小数的其中的一个

,那么这个树直接往上生长就可以了,如果这两个数的和比较大,不是下一步的两个最小数的其中一个,那么就并列生

长。)

(4)从19,21,7,10,32,11中选出两个权小结点。选中7,10。同时计算出它们的和17。 (BTW:这时选出的两个数字都不是已经构造好的二叉树里面的结点,所以要另外开一棵二叉树;或者说,如果两个数的和正好是下一步的两个最小数的其中的一个,那么这个树直接往上生长就可以了,如果这两个数的和比较大,不是下一步的两个最小数的其中一个,那么就并列生长。)

(5)从19,21,32,11,17中选出两个权小结点。选中11,17。同时计算出它们的和28。

(6)从19,21,32,28中选出两个权小结点。选中19,21。同时计算出它们的和40。另起一颗二叉树。

(7)从32,28, 40中选出两个权小结点。选中28,32。同时计算出它们的和60。

(8)从 40, 60中选出两个权小结点。选中40,60。同时计算出它们的和100。 好了,此时哈夫曼树已经构建好了。

这是原作者的链接哦,我觉得还不错呢,大家可以去看看的!

注意:哈夫曼树并不唯一,但带权路径长度一定是相同的。

(1)8个结点的权值大小如下:

(2)从19,21,2,3,6,7,10,32中选择两个权小结点。选中2,3。同时算出这两个结点的和5。

(3)从19,21,6,7,10,32,5中选出两个权小结点。选中5,6。同时计算出它们的和11。

(4)从19,21,7,10,32,11中选出两个权小结点。选中7,10。同时计算出它们的和17。 (BTW:这时选出的两个数字都不是已经构造好的二叉树里面的结点,所以要另外开一棵二叉树;或者说,如果两个数的和正好是下一步的两个最小数的其中的一个,那么这个树直接往上生长就可以了,如果这两个数的和比较大,不是下一步的两个最小数的其中一个,那么就并列生长。)

(4)从19,21,7,10,32,11中选出两个权小结点。选中7,10。同时计算出它们的和17。

(BTW:这时选出的

两个数字都不是已经构造好的二叉树里面的结点

,所以要另外开一棵二叉树;或者说,

如果两个数的和正好是下一步的两个最小数的其中的一个

,那么这个树直接往上生长就可以了,如果这两个数的和比较大,不是下一步的两个最小数的其中一个,那么就并列生

长。)

(4)从19,21,7,10,32,11中选出两个权小结点。选中7,10。同时计算出它们的和17。 (BTW:这时选出的两个数字都不是已经构造好的二叉树里面的结点,所以要另外开一棵二叉树;或者说,如果两个数的和正好是下一步的两个最小数的其中的一个,那么这个树直接往上生长就可以了,如果这两个数的和比较大,不是下一步的两个最小数的其中一个,那么就并列生长。)

(5)从19,21,32,11,17中选出两个权小结点。选中11,17。同时计算出它们的和28。

(6)从19,21,32,28中选出两个权小结点。选中19,21。同时计算出它们的和40。另起一颗二叉树。

(7)从32,28, 40中选出两个权小结点。选中28,32。同时计算出它们的和60。

(8)从 40, 60中选出两个权小结点。选中40,60。同时计算出它们的和100。 好了,此时哈夫曼树已经构建好了。

 

 

 

 

 

 


http://chatgpt.dhexx.cn/article/wogWLm4m.shtml

相关文章

哈夫曼树(Huffmantree)

1.基本概念 哈夫曼树又称为最优树,是一类带权路径长度最短的树。 一些概念的定义: (1)路径:树的两个结点之间的连线称为路径。 (2)路径长度:路径上的分支数目称作路径长度。若规定…

哈夫曼树详解及其应用(哈夫曼编码)

一,哈夫曼树的基本概念 路径:从树中一个结点到另一个结点之间的分支构成这两个结点间的路径 结点的路径长度:两结点之间路径上的分支数 树的路径长度:从树根到每一个结点的路径长度之和.记作:&#xff3…

哈夫曼树编码的实现+图解(含全部代码)

目录 哈夫曼树的基本概念 ------------哈夫曼树的构造方法 ------------------------哈夫曼编码 ------------------------------------全部代码 哈夫曼树的基本概念 哈夫曼树通常以二叉树的形式出现,所以也称最优二叉树,是一类带权路径长度最短的树…

哈夫曼树(C语言实现)

文章目录 哈夫曼树的基本概念哈夫曼树的构建构建思路代码实现 哈夫曼编码的生成编码生成思路代码实现 完整代码展示以及代码测试 哈夫曼树的基本概念 在认识哈夫曼树之前,你必须知道以下几个基本术语: 1、什么是路径? 在一棵树中&#xff0c…

打开VS2010提示:产品密钥框

打开VS2010提示:产品密钥框,如下图: …

VS 2017 产品密钥

个人分类: vs2010 Visual Studio 2017(VS2017) 企业版 Enterprise 注册码:NJVYC-BMHX2-G77MM-4XJMR-6Q8QF Visual Studio 2017(VS2017) 专业版 Professional 激活码key:KBJFW-NXHK6-W4WJM-CRM…

vs++2010学习版的注册密钥

6VPJ7-H3CXH-HBTPT-X4T74-3YVY7 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 新的改变 我们对Markdown编辑器进行…

存储过程入门

参考文章 Oracle Database concepts guide(11g2) By Thomas KyteStored Procedure Wiki 先修知识 数据库的基本概念SQL 什么是存储过程(Stored Procedure): 一段存储在数据库的“子程序”,下面对这两个…

【MySQL存储过程】创建一个简单的存储过程

什么是存储过程和函数 存储过程和函数是在数据库中定义的一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句。存储过程和函数可以避免开发人员重复编写相同的SQL语句。而且,存储过程和函数是在MySQL服务器中存储和执行的&…

什么是存储过程

什么是存储过程:存储过程可以说是一个记录集吧,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到…

MySQL-存储过程

文章目录 存储过程一. 存储过程的创建和使用1. 创建存储过程2. 删除存储过程3. 查看存储过程4. 调用存储过程5. 例题 二. 变量1. 系统变量1.1 全局变量1.2 会话变量 2. 自定义变量2.1 用户变量2.2 局部变量 三. 存储过程参数3.1 说明:3.2 例题 四. 流程控制1. IF语句…

存储过程怎么使用

1.什么是存储过程? 存储过程是封装了一条或多条SQL的集合。它的好处是简单、高性能、安全。2.为什么要使用存储过程? 简化复杂的操作,把SQL封装起来容易使用。 如果所有开发人员和应用程序都使用同一存储过程,则所有使用的代码都…

SQL创建存储过程

创建SQL存储过程需要使用到的语法 - 创建存储过程 CREATE 存储过程的名称(参数) BEGIN ...需要执行的SQL语句 END- 调用 CALL 存储过程的名称(参数)个人看法,这就是一个函数...无参数 CREATE PROCEDURE p_student_select() BEGIN SELECT * FROM student; ENDCALL …

4.3.1 存储过程的简要介绍

4.3.1 存储过程的简要介绍 1、什么是存储过程? 存储过程是一种命名的PL/SQL代码块。它既可以没有参数,也可以有若干输入、输出参数,甚至可以有多个既作输入又作输出的参数,但他通常没有返回值。 存储过程被保存在数据库中&#x…

储存过程

储存过程是一组为了完成特定功能的SQL语句表,经过编译后储存在数据库中,用户通过指定过程的名字并给定参数来调用执行它。 从常用的操作数据库的SQL语句在执行的时候需要先编译,然后执行,储存过程,则是采用另外一种方式…

java笔试--北京轩宇信息

第一题 import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths;/*** <p>功能: 编写程序,在C盘根目录下创建文件myFile.txt&#xff0c;文件内容如下&#xff0c;请注意缩进和换行&#xff1a;* Java* C/C* Python* JavaScripts*/ public…

笔试——中兴

参考达尔文公众号&#xff1a;https://mp.weixin.qq.com/s?__bizMzg5MDIwNjIwMA&mid2247496018&idx1&snf8109b6f5b5ea3a175e52eb7074bb7bc&chksmcfe293c5f8951ad3570a64a07ce0deba1ec12f3c8d0a15bbf1c64ed25e5faca46ef5974fef72&mpshare1&scene23&…

中兴2016笔试题答案Java_中兴Java笔试题

中兴Java笔试题 一、选择题(每题4分,共80分) 1. 编译Java Application 源程序文件将产生相应的字节码文件&#xff0c;这些字节码文件的扩展名为( ) A. .java B. .class C. .html D. . 2. main方法是Java Application程序执行的入口点&#xff0c;关于main方法的方法头以下哪项…

中兴通讯2013校招软件笔试题

关于const的实现机制&#xff0c;请看&#xff1a; http://blog.csdn.net/syzcch/article/details/8182184 define宏定义那个题&#xff1a; http://zhidao.baidu.com/link?urltSvmJ_ytFjwWKBLzDgCfLfW-mdJtTChTab3XzBAbd2x1nGYQCGnqDq__9-dqc_ndlWE1uPeaFcyVXlKOn1CAha …

中兴笔试程序题

文本编辑器&#xff08;15&#xff09; 要求&#xff1a; &#xff08;1&#xff09;编辑文本&#xff1b; &#xff08;2&#xff09;保存、打开指定位置的文本文件&#xff1b; &#xff08;3&#xff09;具有输入输出界面。 代码&#xff1a;&#xff08;此代码在vc6.…