前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >原以为哈夫曼树、哈夫曼编码很难,结果……

原以为哈夫曼树、哈夫曼编码很难,结果……

作者头像
main方法
发布于 2021-07-19 02:58:31
发布于 2021-07-19 02:58:31
67600
代码可运行
举报
文章被收录于专栏:main方法main方法
运行总次数:0
代码可运行

哈夫曼树介绍

大家好,我是bigsai。原以为哈夫曼树、哈夫曼编码很难,结果它很简单啊老铁们!

哈夫曼树、哈夫曼编码很多人可能听过,但是可能并没有认真学习了解,今天这篇就比较详细的讲一下哈夫曼树。

首先哈夫曼树是什么?

哈夫曼树的定义:给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree),哈夫曼树是带权路径长度最短的树。权值较大的结点离根较近。

那这个树长啥样子呢?例如开始2,3,6,8,9权值节点构成的哈夫曼树是这样的:

从定义和图上你也可以发现下面的规律:

  • 初始节点都在树的叶子节点上
  • 权值大的节点离根更近
  • 每个非叶子节点都有两个孩子(因为我们自下向上构造,两个孩子构成一个新树的根节点)

你可能会好奇这么一个哈夫曼树是怎么构造的,其实它是按照一个贪心思想和规则构造,而构造出来的这个树的权值最小。这个规则下面会具体讲解。

哈夫曼树非常重要的一点:WPL(树的所有叶结点的带权路径长度之和)。至于为什么按照哈夫曼树方法构造得到的权重最小,这里不进行证明,但是你从局部来看(三个节点)也要权值大的在上一层WPL才更低。

WPL计算方法: WPL=求和(Wi * Li)其中Wi是第i个节点的权值(value)。Li是第i个节点的长(深)度.

例如上面 2,3,6,8,9权值节点构成的哈夫曼树的WPL计算为(设根为第0层):

比如上述哈夫曼树的WPL为:2*3+3*3+6*2+8*2+9*2=(2+3)*3+(6+8+9)*2=61.

既然了解了哈夫曼树的一些概念和WPL的计算方式,下面看看哈夫曼树的具体构造方式吧!

哈夫曼树构造

初始给一个森林有n个节点。我们主要使用贪心的思想来完成哈夫曼树的构造:

  1. 在n个节点找到两个最小权值节点(根),两个为叶子结构构建一棵新树(根节点权值为左右孩子权值和)
  2. 先删掉两个最小节点(n-2)个,然后加入构建的新节点(n-1)个
  3. 重复上面操作,一直到所有节点都被处理

在具体实现上,找到最小两个节点需要排序操作,我们来看看2,6,8,9,3权值节点构成哈夫曼树的过程。

初始时候各个节点独立,先将其排序(这里使用优先队列),然后选两个最小节点(抛出)生成一个新的节点,再将其加入优先队列中,此次操作完成后优先队列中有5,6,8,9节点

重复上面操作,这次结束 队列中有11,8,9节点(排序后8,9,11)

如果队列为空,那么返回节点,并且这个节点为整个哈夫曼树根节点root。

否则继续加入队列进行排序。重复上述操作,直到队列为空

在计算带权路径长度WPL的时候,需要重新计算高度(从下往上),因为哈夫曼树是从下往上构造的,并没有以常量维护高度,可以构造好然后计算高度。

具体代码实现(仅供参考)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;

public class HuffmanTree {    
    public static class node
    {
        int value;
        node left;
        node right;
        int deep;//记录深度
        public node(int value) {
            this.value=value;
            this.deep=0;
        }
        public node(node n1, node n2, int value) {
            this.left=n1;
            this.right=n2;
            this.value=value;
        }
    }
    private node root;//最后生成的根节点
    List<node>nodes;
    public HuffmanTree() {
        this.nodes=null;
    }
    public HuffmanTree(List<node>nodes)
    {
        this.nodes=nodes;
    }
    public void createTree() {
       Queue<node>q1=new PriorityQueue<node>(new Comparator<node>() {
      public int compare(node o1, node o2) {
        return o1.value-o2.value;
      }});
       q1.addAll(nodes);
       while(!q1.isEmpty()){
           node n1=q1.poll();
           node n2=q1.poll();
          node parent=new node(n1,n2,n1.value+n2.value);
          if(q1.isEmpty()){
              root=parent;return;
          }
          q1.add(parent);
       }
    }
    public int getweight() {
        Queue<node>q1=new ArrayDeque<node>();
        q1.add(root);
        int weight=0;
        while (!q1.isEmpty()) {
            node va=q1.poll();
            if(va.left!=null){
                va.left.deep=va.deep+1;va.right.deep=va.deep+1;
                q1.add(va.left);q1.add(va.right);
            }
            else {
                weight+=va.deep*va.value;
            }
        }
        return weight;
    }
    public static void main(String[] args) {
        List<node>list=new ArrayList<node>();
        list.add(new node(2));
        list.add(new node(3));
        list.add(new node(6));
        list.add(new node(8));list.add(new node(9));
        HuffmanTree tree=new HuffmanTree();
        tree.nodes=list;
        tree.createTree();
        System.out.println(tree.getweight());
    }
}

输出结果:

61

哈夫曼编码

除了哈夫曼树你听过,哈夫曼编码你可能也听过,但是不一定了解它是个什么玩意儿,哈夫曼编码其实就是哈夫曼树的一个非常重要的应用,在这里就简单介绍原理并不详细实现了。

哈夫曼编码定义:哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式,哈夫曼编码是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫做Huffman编码(有时也称为霍夫曼编码)。

哈夫曼编码的目的是为了减少存储体积,以一个连续的字符串为例,抛开编程语言中实际存储,就拿

aaaaaaaaaabbbbbcccdde

这个字符串来说,在计算机中如果每个字符都是定长存储(假设长为4的二进制存储),计算机只知道0和1的二进制,假设

a:0001 b:0010 c:0011 d:0100 e:0101

那么上面字符串可以用二进制存储是这样的

000100010001000100010001……0101

如果每个字符编码等长,那么就没有存储空间优化可言,都是单个字符长度 * 字符个数。但是如果每个字符编码不等长,那么设计的开放性就很强了。

比如一个字符串aaaaabb

如果设计a为01,b设计为1。那么二进制就为:010101010111

如果设计a为1,b设计为01。那么二进制就为:111110101

如果设计a为1,b设计为0。那么二进制就为:1111100

你看,在计算机的01二进制世界中,明显第二种比第一种优先,第三种又比第二种优先。所以,设计编码要考虑让出现多的尽量更短,出现少的稍微长点没关系

但是,你需要考虑的一个问题是,二进制开始0,1,01,10,11这个顺序 ,如果来了001它到底是0,0,1还是0,01呢?所以编码不等长的时候你要考虑到这个编码要有唯一性不能出现歧义。这个怎么搞呢?

简单啊,计算机只知道01二进制,而二叉树刚好有左右两个节点,至于一个字符它如果是对应叶子节点,那么就可以直接确定,也就是这个数值如果映射成一个二叉树字符不能存在非叶子节点上。

所以,哈夫曼编码具体流程就很清晰了,先统计字符出现的次数,然后将这个次数当成权值按照上面介绍的方法构造一棵哈夫曼树,然后树的根不存,往左为0往右为1每个叶子节点得到的二进制数字就是它的编码,这样频率高的字符在上面更短在整个二进制存储中也更节省空间。

结语

哈夫曼树还是比较容易理解,主要构造利用贪心算法的思想去从下往上构建,哈夫曼编码相信看了你也有所收获,有兴趣可以自己实现一下哈夫曼编码的代码(编码、解码)。本人水平有限,如果有错误还希望大佬指正!

点个在看你最好看

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 main方法 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
哈夫曼树(最优二叉树)详解与构造
其中WPL表示计算出的权值。至于为什么按照哈夫曼树方法构造得到的权重最小。这里不进行证明。对于哈夫曼树,他的每个非叶子节点都有两个孩子因为哈夫曼树的构造就是自底向上的构造,两两合并。
bigsai
2019/09/24
6.9K0
哈夫曼树(最优二叉树)详解与构造
【数据结构】哈曼夫树与哈夫曼编码
在上一篇内容中我们介绍了树与森林的遍历,并且我们还通过C语言实现了树与森林的遍历。
蒙奇D索隆
2025/03/20
1750
【数据结构】哈曼夫树与哈夫曼编码
构造哈夫曼树的算法_哈夫曼树的应用数据结构
给定n个权值作为n个叶子节点,构造一课二叉树,若该树的带权路径长度和(wpl)达到最小,称这样的二叉树为最优二叉树,也就是赫夫曼树。
全栈程序员站长
2022/09/23
4710
构造哈夫曼树的算法_哈夫曼树的应用数据结构
哈夫曼树的详细讲解(手把手教学)
哈夫曼树又称为最优树,是一类带权路径长度最短的树,应用光泛。 在学习哈夫曼树的时候,我们来先引入路径和路径长度的概念。 ***1.1路径:***从树中的一个结点到另一个结点的之间的分支构成的。 ***1.2路径长度:***路径上的分支数目。 ***1.3树的路径长度:***从树根到每一个结点的路径长度之和 结点的带权路径长度:从该结点到树根之间的路径长度与结点上的权值的乘积 ***1.4树的带权路径长度:***树中所有叶子结点的·带权路径长度之和,也就是WPL,WPL=每一个结点的对应的权值乘以对应的路径长度之和。 注意: 1.满二叉树不一定是哈夫曼树 2.哈夫曼树中权值越大的叶子结点离根越近 3.具有相同带权结点的哈夫曼树不惟一 4.在结点相同的二叉树中,完全二叉树是路径长度最短的二叉树。
洁洁
2023/10/10
8350
哈夫曼树的详细讲解(手把手教学)
【算法】赫夫曼树(Huffman)的构建和应用(编码、译码)
参考资料 《算法(java)》                           — — Robert Sedgewick, Kevin Wayne 《数据结构》                                  — — 严蔚敏 赫夫曼树的概念 要了解赫夫曼树,我们要首先从扩充二叉树说起 二叉树结点的度 结点的度指的是二叉树结点的分支数目, 如果某个结点没有孩子结点,即没有分支,那么它的度是0;如果有一个孩子结点, 那么它的度数是1;如果既有左孩子也有右孩子, 那么这个结点的度是2. 扩充
啦啦啦321
2018/03/30
2K0
【算法】赫夫曼树(Huffman)的构建和应用(编码、译码)
数据结构(五):哈夫曼树(Huffman Tree)
哈夫曼树(或者赫夫曼树、霍夫曼树),指的是一种满二叉树,该类型二叉树具有一项特性,即树的带权路径长最小,所以也称之为最优二叉树。
zhipingChen
2018/09/13
2.9K0
数据结构(五):哈夫曼树(Huffman Tree)
哈夫曼树与哈夫曼编码:聪明的数据压缩技术
👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.
Lorin 洛林
2023/11/14
1.1K1
哈夫曼树与哈夫曼编码:聪明的数据压缩技术
数据结构09 哈夫曼树
这一篇要总结的是树中的哈夫曼树(Huffman Tree),我想从以下几点对其进行总结: 1、什么是哈夫曼树 2、如何构建哈夫曼树 3、哈夫曼编码 4、代码实现 1、什么是哈夫曼树 什么是哈夫曼树
nnngu
2018/03/15
7900
数据结构09 哈夫曼树
C++ 漫谈哈夫曼树
则称符合上述条件的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。
一枚大果壳
2022/08/23
6680
C++ 漫谈哈夫曼树
数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现
0. 数据结构图文解析系列 数据结构系列文章 数据结构图文解析之:数组、单链表、双链表介绍及C++模板实现 数据结构图文解析之:栈的简介及C++模板实现 数据结构图文解析之:队列详解与C++模板实现 数据结构图文解析之:树的简介及二叉排序树C++模板实现. 数据结构图文解析之:AVL树详解及C++模板实现 数据结构图文解析之:二叉堆详解及C++模板实现 数据结构图文解析之:哈夫曼树与哈夫曼编码详解及C++模板实现 数据结构图文解析之:直接插入排序及其优化(二分插入排序)解析及C++实现 1. 哈夫曼编码简
Tencent JCoder
2018/07/02
1.1K0
【数据结构】建立二叉树以及哈夫曼树及哈夫曼编码
文章目录 5.4.1 方式 5.4.2 由先根和中根遍历序列建二叉树 5.4.3 由后根和中根遍历序列建二叉树 5.4.4 由标明空子树的先根遍历建立二叉树 5.4.5 由完全二叉树的顺序存储结构建立二叉链式存储结构 5.5 哈夫曼树及哈夫曼编码 5.5.1 基本概念 5.5.2 最优二叉树 5.5.3 构建哈夫曼树 5.5.4 哈夫曼编码 5.5.5 哈夫曼编码类 5.4.1 方式 四种方式可以建立二叉树 由先根和中根遍历序列建二叉树 由后根和中根遍历序列建二叉树 由标明空子树的先根遍
陶然同学
2023/02/26
1.1K0
【数据结构】建立二叉树以及哈夫曼树及哈夫曼编码
哈夫曼树(郝夫曼树)及java实现
哈夫曼树是美国数学家Huffman发现的一种数据结构,该数据结构用在哈夫曼编码中,哈夫曼编码是一种压缩算法,本文主要针对的是哈夫曼树这种数据结构,哈夫曼编码将在下篇博文中涉及。
johnhuster的分享
2022/03/28
5040
哈夫曼树(郝夫曼树)及java实现
赫夫曼树
给定N个权值作为N个叶子节点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为最优二叉树,也成为哈夫曼树(huffman-tree),还有的树翻译为霍夫曼树。
JusterZhu
2022/12/07
2420
赫夫曼树
[数据结构与算法]赫夫曼树与赫夫曼编码
给你一个数列 {13, 7, 8, 3, 29, 6, 1},要求转成一颗赫夫曼树.
时间静止不是简史
2020/07/24
1.2K0
哈夫曼树、哈夫曼编码和字典树
        哈夫曼树(Huffman Tree)是一种带权路径长度最短的二叉树。哈夫曼树常常用于数据压缩,其压缩效率比较高。
周小末天天开心
2023/10/16
5700
哈夫曼树、哈夫曼编码和字典树
哈夫曼树(Java实现)
①、给定n个权值作为n个叶子节点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为最优二叉树,也称哈夫曼树(Huffman Tree)、赫夫曼树、霍夫曼树。 ②、哈夫曼树是带权路径长度最短的树,权值较大的节点离根较近
技术交流
2022/11/18
5970
哈夫曼树(Java实现)
哈夫曼编码
构建最短带权路径长度的二叉树,叫做哈夫曼树,也叫最优树(权重越大的结点离树根越近)
晚上没宵夜
2022/05/09
4070
哈夫曼编码
哈夫曼树学习笔记-构建哈夫曼树
哈夫曼树(Huffman Tree)是一种用于数据压缩的树形数据结构,由David A. Huffman在1952年发明。哈夫曼树通常用于无损数据压缩中,将出现频率高的字符编码成较短的二进制序列,从而减少数据的存储空间。
吃猫的鱼Code
2023/05/22
1.5K0
哈夫曼树学习笔记-构建哈夫曼树
最优二叉树—哈夫曼(huffman)树
ASL=(1+2*2+3)/4=2            ASL=(1+2+3+4)/4=2.5
一条晒干的咸鱼
2024/11/19
3140
最优二叉树—哈夫曼(huffman)树
数据结构 Huffman树
Huffman 介绍 哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点
Kindear
2017/12/29
1.5K0
数据结构 Huffman树
相关推荐
哈夫曼树(最优二叉树)详解与构造
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验