有趣的赫夫曼树

美国有个数学家叫赫夫曼,60年前他根据数据的使用概率,发明了一个二叉树叫赫夫曼树。

这个赫夫曼树被用在了数据压缩上,被称为赫夫曼编码,这是后来压缩的基础。

他解决的问题主要思想是:根据元素出现的概率,获得最优解。

举例如下:

学生考试成绩出来后,会根据考试成绩分等级,极优秀,优秀,中等,及格,不及格。如果我们按照普通逻辑进行判断时,通常是:

    if (Score < 60) {
        printf("不及格");
    } else if (Score < 70) {
        printf("及格");
    } else if (Score < 80) {
        printf("中等");
    } else if (Score < 90) {
        printf("优秀");
    } else if (Score < 100) {
        printf("极优秀");
    }

但是按照分数的分布概率,优秀:30%,中等:40%,及格:15%,极优秀:10%,不及格:5%

如果先判断优秀,中等,再判断极优秀,极优秀,不及格,则可以提高很多效率。

赫夫曼树就是根据概率来生成的二叉树。

转换成二叉树区别如下:

从根节点出发,遍历每一个叶子节点,是的到达节点时走的链接树乘以节点(nodeLinkNum * weight)对应的权重之和最小

如:

sum = 1*5+2*15+3*40+4*30+4*10

显然,左图和右图总和不一样,左图的和大于右图.

那给你一组数字,怎么构造一个赫夫曼树呢?

1.先把所有的数据节点,从小到大依次排列,成为一个有序列表

2.取出前面两个节点,让这两个节点的权重数据相加得到一个和,令这个和为根节点,这个两个节点的小的为其左孩子,大的为其右孩子

3.令这个和节点替换掉前面的两个节点,并重新排序,生成一个有序列表

4.不断重复第二步,第三步。直到所有的节点都被用完,得到一个排序结果,此时生成的二叉树,就是赫夫曼树。

赫夫曼树的实际应用:压缩数据

数据在计算机的表示形式是0,1,那么一串字符串的表示是怎么样的呢

例如ABCDEF编码如下:

那么要表示字符串“BADCADFEED”的二进制为:“001000011010000011101100100011”。

但是ABCDEF做为基本字符,在这串字符串中的出现概率是不一样的,那么我们是否可以以概率做为字符权重,对字符生成赫夫曼树呢

假设六个字母的频率为A 27,B 8,C 15,D15,E 30,F 5,合起来正好是100%。那就意味着,我们完全可以重新按照赫夫曼树来规划它们。

将权值左分支改为0,右分支改为1后的赫夫曼树。

根据重新编码后为:

1001010010101001000111100(共25个字符)

而原来的字符编码为:

“001000011010000011101100100011”(共30个字符)

压缩了近17%

解压时,按照同样的规则,还原原字符串。

原文地址:https://www.cnblogs.com/zhou--fei/p/10005253.html

时间: 2024-10-21 05:03:01

有趣的赫夫曼树的相关文章

由二叉树构造赫夫曼树

赫夫曼树: 假设有n个权值{w1,w2,w3....},试构造一棵具有n个叶子节点的二叉树,每个叶子节点带权为wi,则其中带权路径长度最小的二叉树称为最优二叉树或者叫赫夫曼树. 构造赫夫曼树: 假设有n个权值,则构造出的赫夫曼树有n个叶子节点,n个权值分别设置为w1,w2,....wn,则赫夫曼树的构造规则为: 1.将w1,w2...看成是有n棵树的森林: 2.在森林中选择两个根节点的权值最小的树合并,作为一棵新树的左右子树,且新树的根节点权值为其左右子树根节点权值之和: 3.从森林中删除选取的

php 二叉树 与赫夫曼树

在学习图之前,中间休息了两天,感觉二叉树需要消化一下.所以中间去温习了下sql,推荐一本工具书<程序员的SQL金典>看名字不像一本好书,但是作为一个不错的SQL工具书还是可以小小备忘一下.涵盖内容不详细但是挺广,覆盖多种主流数据库 言归正传,以前知道折半查找,二叉树的概念也是感觉挺有意思,二叉树的实现有一个案例很不错,代码如下 class BiNode{ public $data; public $lchild; public $rchild; public function __constr

Huffman tree(赫夫曼树、霍夫曼树、哈夫曼树、最优二叉树)

flyfish 2015-8-1 Huffman tree因为翻译不同所以有其他的名字 赫夫曼树.霍夫曼树.哈夫曼树 定义引用自严蔚敏<数据结构> 路径 从树中一个结点到另一个结点之间的分支构成两个结点之间的路径. 路径长度 路径上的分支数目称作路径长度. 树的路径长度 树的路径长度就是从根节点到每一结点的路径长度之和. 结点的带权路径长度 结点的带权路径长度就是从该结点到根节点之间的路径长度与结点上权的乘积. 树的带权路径长度 树的带权路径长度就是树中所有叶子结点的带权路径长度之和,通常记做

赫夫曼树JAVA实现及分析

一,介绍 1)构造赫夫曼树的算法是一个贪心算法,贪心的地方在于:总是选取当前频率(权值)最低的两个结点来进行合并,构造新结点. 2)使用最小堆来选取频率最小的节点,有助于提高算法效率,因为要选频率最低的,要么用排序,要么用堆.用堆的话,出堆的复杂度为O(logN),而向堆中插入一个元素的平均时间复杂度为O(1),在构建赫夫曼树的过程中,新生成的结点需要插入到原来的队列中,故用堆来维持这种顺序比排序算法要高效地多. 二,赫夫曼算法分析 ①用到的数据结构分析 首先需要构造一棵赫夫曼树,因此需要二叉链

13.赫夫曼树及其应用

一.赫夫曼树定义与原理 1.路径长度:从树中一个结点到另一个结点之间的分支构成两个结点之间的路径,路径上的分支数目称作路径的长度; 2.树的路径长度:即从树根到每一结点的路径长度之和; 3.结点的带权的路径长度:即从该结点从到树根之间的路径长度与结点上权的乘积; 4.树的带权路径长度:为树中所有叶子结点的带权路径长度之和; 5.赫夫曼树定义:假设有n个权值{w1,w2,....,wn},构造一颗有n个叶子结点的二叉树,每个叶子结点带权wk,每个叶子的路径长度为lk,则其中带权路径长度WPL最小的

赫夫曼树(最优二叉树)

.在选择最小s1s2的时候少了一个空语句分号..调试了好久..坑爹. 这个是最优的编码策略能达到最少的编码 1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 #include<math.h> 5 #include<queue> 6 #include<algorithm> 7 using namespace std; 8 typedef struct 9 {

【数据结构】赫夫曼树的实现和模拟压缩(C++)

赫夫曼(Huffman)树,由发明它的人物命名,又称最优树,是一类带权路径最短的二叉树,主要用于数据压缩传输. 赫夫曼树的构造过程相对比较简单,要理解赫夫曼数,要先了解赫夫曼编码. 对一组出现频率不同的字符进行01编码,如果设计等长的编码方法,不会出现混淆的方法,根据规定长度的编码进行翻译,有且只有一个字符与之对应.比如设计两位编码的方法,A,B,C,D字符可以用00-11来表示,接收方只要依次取两位编码进行翻译就可以得出原数据,但如果原数据只由n个A组成的,那发出的编码就是2n个0组成,这样的

基础数据结构-二叉树-赫夫曼树的解码(详解)

本篇是上一篇赫夫曼树构建与编码的后续,稍微详细讲一下解码的算法. Huffman解码算法流程: 1.定义指针p指向赫夫曼树结点,实际是记录结点数组的下标: 2.定义指针i指向编码串,定义ch逐个取编码串的字符: 3.初始化:读入编码串,设置p指向根结点,i为0: 4.执行以下循环: a)取编码串的第i个字符放入ch: b)如果ch是字符0,表示往左孩子移动,则p跳转到右孩子: c)如果ch是字符1,表示往右孩子移动,则p跳转到右孩子: d)如果ch非0非1,表示编码串有错误,输出error表示解

赫夫曼树

一.前言 赫夫曼树,又称最优树,是一类带权路径长度最短的树. 二.基础知识 1.路径长度:从树中一个结点到另一个结点之间的分支构成这两个结点之间的路径,路径上分支数目称为路径长度. 2.树的路径长度:是从树根到每一个结点的路径长度之和.完全二叉树就是路径长度最短的二叉树. 3.树带权路径长度:为树中所有叶子结点的带权路径长度之和(记做WPL). 4.最优二叉树或者赫夫曼树:假设有n个权值(w1,w2,w3,w4,,,,,,wn).试构造一棵有n个叶子结点的二叉树,每个叶子结点带权为wi,其中称带