数据结构--哈夫曼树

一、 一些基本概念
1、 路径长度
树中一个结点到另一个结点之间的分支构成这两个结点之间的路径,路径上的分支数目为路径长度


image.png

上图中,从1到4的路径长度为2,从7 到3的路径长度为4

2、 树的路径长度
从树根到每一个结点的路径长度之和,这种路径长度最短的树是完全二叉树
上图中,树的路径长度为:1 + 1 + 2 + 2 + 3 + 3 = 12

3、 权
若将树中结点赋一个有某种含义的数值,则这个数值称为该结点的权

4、 结点的带权路径长度
从根结点到该结点间的路径长度与该结点的权的乘积

2、 树的路径长度
从树根到每一个结点的路径长度之和,这种路径长度最短的树是完全二叉树
上图中,树的路径长度为:1 + 1 + 2 + 2 + 3 + 3 = 12

3、 权
若将树中结点赋一个有某种含义的数值,则这个数值称为该结点的权

4、 结点的带权路径长度
从根结点到该结点间的路径长度与该结点的权的乘积

2、 树的路径长度
从树根到每一个结点的路径长度之和,这种路径长度最短的树是完全二叉树
上图中,树的路径长度为:1 + 1 + 2 + 2 + 3 + 3 = 12

3、 权
若将树中结点赋一个有某种含义的数值,则这个数值称为该结点的权

4、 结点的带权路径长度
从根结点到该结点间的路径长度与该结点的权的乘积


image.png

上图中,结点d的带权路径长度为:4 X 3 = 12

5、 树的带权路径长度WPL
树中所有带权结点的路径长度之和
上图中,树的带权路径长度WPL为:7 X 1 + 5 X 2 + 2 X 3 + 4 X 3 = 35

6、 哈夫曼树(最优二叉树)
有n个叶子结点的二叉树,每个叶子结点均带权,带权路径长度WPL最小的二叉树即为哈夫曼树

二、 哈夫曼树的构造
1、 给定n个权值{w1, w2, w3 …… wn}构成 n棵二叉树的集合F = {T1, T2, T3 …… Tn}, 其中每棵树只有权值为Wi的根节点,其左右子树均为空。
例如,给定结点的权值为7 5 2 4,构造出树如下:


image.png

2、 在二叉树集合F中选取两棵根结点的权值最小的树作为左右子树,构造一棵新的二叉树,且新的二叉树的根节点的权值为其左右子树结点的权值之和。
3、 在F中删除这两棵树,并将新的二叉树加入到F中


image.png

4、 重复2、3,直到F只含一棵树为止,这棵树便是哈夫曼树
image.png

三、 哈夫曼树的应用--得到最佳判定算法
例如,编制一个将百分制转换成五分制的程序,判定过程可用判定树来表示


image.png

如果分数小于60,我们做1次判断即可;如果分数为60~70,需要判断2次;如果分数为70~80,需要判断3次;如果分数为80~90,需要判断4次;如果分数为90~100,需要判断5次。
在实际中,学生成绩在五个等级上的分布上不均匀的,假设分布规律如下:


image.png

如果有100个数据,判断次数为:100 X 5% X 1 + 100 X 15% X 2 + 100 X 40% X 3 + 100 X 30% X 4 + 100 X 10% X 5 = 325
如果每次输入的量很大,就需要考虑尽量减少判断次数,降低程序的运行时间。
从上面的分布图上可看出,80%以上的数据需要进行三次或更多次的比较才能得到结果,但如果以5,15,40,30,10作为权,构造一棵有5个叶子结点的哈夫曼树,可得到:
image.png

这样对100个数据进行判断,次数为:100 X 5% X 4 + 100 X 15% X 3 + 100 X 40% X 1 + 100 X 30% X 2 + 100 X 10% X 4 = 205
这样可以使大部分数据经过教少的比较次数得出结果。把每个判定框内的两次比较分开,得到最终的判定树,如下:


image.png

四、哈夫曼编码
1、 定长编码与变长编码
在处理字符串序列时,如果对每个字符串采用相同的二进制位来表示,则称这种编码方式为定长编码。假如传送的电文为“A B A C C D A”,编码分别为00、01、10、11,则上述电文便为“00010010101100”,译码时按二位一分进行译码。但传送电文时,希望电文长度尽可能短,因此可采用变长编码方式,即对不同的字符采用不等长的二进制位进行表示。可变长编码的特点就是,对使用频率高的字符采用短编码,而对使用频率低的字符采用长编码的方式。这样我们就可以减少数据的存储空间,从而起到压缩数据的效果。
采用变长编码方式需要解决两个问题
A、 编码尽可能短。这样可以提高压缩率,节省空间,提高运输和通信速度
B、 不能有二义性。如果设计A、B、C、D的编码为0、00、1、01,如果传送的字串为“0000”,译码时可以译为AAAA、ABA、BB等,不唯一,所以必须采用前缀编码,也就是说任一个字符的编码都不是另一个字符的编码的前缀。如0,101和100是前缀编码。由前缀码形成的序列可以被唯一的组成一个字符串序列。如00101100可以被唯一的分析为0,0,101和100。
哈夫曼编码就很好的解决了上面两个问题。
2、 设计前缀编码
可以利用二叉树来设计前缀编码,如下图所示二叉树,叶子结点为A、B、C、D,且左分支表示0,有分支表示1,则以从根结点到叶子结点的路径上的分支字符组成的字符串作为该叶子结点字符的编码,这个编码即为二进制前缀编码,可得A、B、C、D的编码0、10、110、111。
image.png

3、 哈夫曼编码

哈夫曼编码的基本思想是以字符的使用频率作为权,构造一棵哈夫曼树,然后利用哈夫曼树对字符进行编码。这棵哈夫曼树,是将所要编码的字符作为叶子结点,该字符在文件中的使用频率作为叶子结点的权,以自底向上的方式,通过n-1次合并运算后构造出一棵树,权值越大的叶子离根越近。

4、 哈夫曼树的数据结构
哈夫曼树中没有度为1的结点,则一棵有n个叶子结点的哈夫曼树共有2n – 1个结点(n – 1次合并,每次产生一个新结点),对每个结点而言,需要知道双亲和孩子的信息,因此设定的存储结构如下

typedef struct 
{ 
    double weight; //权值
    int parent; //双亲
    int lchild; //左孩子 
    int rchild; //右孩子 
    char value; //该节点表示的字符 
} HNodeType;

5、 构造哈夫曼树

int i, j, x1, x2; //x1、x2为两个最小权值结点的序号。 
double m1,m2; //m1、m2为两个最小权值结点的权值。 
for (i=0; i<n-1; i++)  { 
    m1=m2=MAXVALUE; //初始化为最大值 
    x1=x2=-1; //初始化为-1 
    //找出所有结点中权值最小、无双亲结点的两个结点 
    for (j=0; j<n+i; j++)  { 
        if (HuffNode[j].weight < m1 && HuffNode[j].parent==-1)  { 
            m2 = m1; 
            x2 = x1; 
            m1 = HuffNode[j].weight; 
            x1 = j; 
        } else if (HuffNode[j].weight < m2 && HuffNode[j].parent==-1)  { 
            m2=HuffNode[j].weight; 
            x2=j; 
        }
    } 
    /* 更新新树信息 */ 
    HuffNode[x1].parent = n+i; //x1的父亲为新结点编号n+i
    HuffNode[x2].parent = n+i; //x2的父亲为新结点编号n+i
    HuffNode[n+i].weight =m1+m2; //新结点权值为两个最小权值之和m1+m2
    HuffNode[n+i].lchild = x1; //新结点n+i的左孩子为x1
    HuffNode[n+i].rchild = x2; //新结点n+i的右孩子为x2
} 

举例:
有一些字符和他们的使用频率,如下图:


image.png

初始化哈夫曼树


image.png

对应的树


image.png

i=0时,j=0;j<6;找双亲为−1,权值最小的两个数:

x1=0 x2=3;//x1、x2为两个最小权值结点的序号 
m1=5 m2=7;//m1、m2为两个最小权值结点的权值 
HuffNode[0].parent = 6; //x1的父亲为新结点编号n+i 
HuffNode[3].parent = 6; //x2的父亲为新结点编号n+i 
HuffNode[6].weight =12; //新结点权值为两个最小权值之和m1+m2 
HuffNode[6].lchild = 0; //新结点n+i的左孩子为x1 
HuffNode[6].rchild = 3; //新结点n+i的右孩子为x2

第一次循环后


image.png

对应的哈夫曼树


image.png

全部循环完成后
image.png

对应的哈夫曼树


image.png

五、 哈夫曼树的应用
1、 数据的压缩:在通信中我们可以先对发送的数据进行哈夫曼编码压缩数据提高传输速度。
2、 查询优化:在查询的时候我们把查询频率最高的数据建立索引提高查询速度

参考http://blog.csdn.net/rainchxy/article/details/78647182

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,392评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,258评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,417评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,992评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,930评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,199评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,652评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,327评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,463评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,382评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,432评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,118评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,704评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,787评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,999评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,476评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,057评论 2 341

推荐阅读更多精彩内容

  • 这篇文章收录在我的 Github 上 algorithms-tutorial,另外记录了些算法题解,感兴趣的可以看...
    Lindz阅读 8,741评论 1 6
  • 你比他好一点,他不会承认你,反而会嫉妒你,只有你比他好很多,他才会承认你,然后还会很崇拜你,所以要做,就一定要比别...
    神经骚栋阅读 2,643评论 5 13
  • 第一章 绪论 什么是数据结构? 数据结构的定义:数据结构是相互之间存在一种或多种特定关系的数据元素的集合。 第二章...
    SeanCheney阅读 5,722评论 0 19
  • 课程介绍 先修课:概率统计,程序设计实习,集合论与图论 后续课:算法分析与设计,编译原理,操作系统,数据库概论,人...
    ShellyWhen阅读 2,233评论 0 3
  • 从毕业后到前段日子,一直都是和同学一起合租,一起游玩,一起学习,一起喜怒哀乐……不过最近产生了一个想法,自己一...
    Persistence的蜗牛阅读 926评论 11 8