zoukankan      html  css  js  c++  java
  • 哈夫曼树的应用

    引子

    期末考试成绩出来了,具体分数不公布,只公布等级,A,B,C,D,E
    老师要根据具体成绩算出每个同学的等级,规则如下
    [85, 100]: A;
    [70, 85): B;
    [60, 70): C;
    [0, 60]: D;
    完成这种映射,可以用下面这个函数来实现

    function rank(score) {
    if (score >= 85) return 'A';
    else if (score >= 70) return 'B';
    else if (score >= 60) return 'C';
    else return 'D';
    }

    这样算是完成了,但是结合实际,我们还有一个条件没利用上,那就是一张合理的试卷,最后结果应该是大多数人中等,高分和低分的人是比较少的。如果我们把第一个if语句的条件改为if(score >= 70 && score <85),那么大多数的成绩只要走一个if,就能够得出结果,统计全部学生等级的时间就会减少。其实,这是一棵普通树转为哈夫曼数的过程。

    分析

    一开始的程序,如果看成一棵树,那么是这样子的。

    而后来的树,是这样子的

    那么如何画出第二棵树,即如何决定哪个判定条件在上面呢?光凭感觉还不行,要有实际的数据去支持。
    遵从一个原则,让数量越多的结果,走越短的路,比如说等级B,中等成绩的学生数量是比较多的,所以我们希望它能在树的上方。

    下面是步骤
    首先要知道每个结果的比重,每个结果是一个叶子节点。
    把叶子节点按照升序排列,取出前两个,构造成一棵新的树,孩子节点就是刚才取出的两个,树根节点的比重是孩子节点比重之和,用这个新的根节点取代刚才的两个孩子节点,与剩下的节点升序排列,重复直到没有叶子节点。

    上面这个例子其实还不是哈夫曼树的最佳应用,把原先的树转化为哈夫曼树,是有缺点的,虽然走的分支少了,但是判定条件变复杂了。
    还有另外的应用,为利用哈夫曼树把字符编码为二进制。
    假设一篇文章里只有ABCDEFGH这八个字母,为了传输这篇文章,要把它转化为二进制。
    容易想到,八个字母,是2的3次方,用三位二进制数就可以表示这八个字母了,而解析的时候,只要按照每3位去解析,就可以还原了。按照这种编码方式(以下称为等长编码),这篇文章编码后的总长度会变为原来字母数量的3倍。要知道,长度越长,传输时间就越长,有没有办法去减少编码后的总长度呢?试想一下一种稍微极端的情况,如果这篇文章中,字母A占据了大多数,如果按照刚才的方法,那么总长度还是不变,如果换一种方法,用0表示A,其他的还是三位,那么显然总长度会变小,把这种想法具体化,就是哈夫曼树了。先统计好每个字母出现的次数,算出每个字母的比重,然后构造哈夫曼树。对每个分支,都左边的设置为0,右边的设置为1,从根结点到叶子节点,走过的分支编号序列,就是该节点对应字符的编码了。假设统计出来的结果是
    A: 40%,B: 20%,C: 10%,D: 10%;E: 5%F:5%;G: 5%H: 5%
    那么构造出来的哈夫曼树是这样子的(结果不唯一)


    各个字符的编码(编码表)
    A:0
    B:100
    C:1010
    D:1011
    E: 1100
    F: 1101
    G:1110
    H: 1111
    如果总共有100个字母,那么用一开始的等长编码方式,长度是300
    用哈夫曼编码,最后的长度是 40*1 + 20*3 + 10 * 4 + 10 * 4 + (5 * 4)*4 = 260
    (300 - 260)/300 = 0.1333 即便是后面的一些字母用4位,最后的长度还是比原来减少了13%。

    字母的编码长度不同,如何去解析呢?实际上,这种编码是前缀码,从左到右扫描编码后的字符串,如果是0,那么该字符就是A,如果是1,那么得继续,直到得到一个在编码表中的编码。

    结语
    要充分地去发掘数据隐含的信息,等长编码的方法因为没有利用字符百分比的信息,所以效果不如哈夫曼编码

    参考:大话数据结构

  • 相关阅读:
    UVA
    codeforces #371div2 B
    POJ-3278 Catch That Cow
    巴士博弈
    权势二进制
    HDU
    SQL 函数
    SQL 查询语句×45
    SQL 触发器
    SQL 连接查询
  • 原文地址:https://www.cnblogs.com/maoscut/p/7602459.html
Copyright © 2011-2022 走看看