2_哈夫曼树和哈夫曼算法

  • 问题

    1. 现在我们要对a,b,c,d,e,f,g 7个字符进行编码,一种笨办法就是每个字符都用3bit进行编码,这样7个字符可以表示为000, 001, 010, 011, 100, 101, 110

    2. 按照上面的编码方式,如果a出现1次,b出现2次,c出现3次……那么这个文件一共要占(1+2+…+7) * 3 = 84bit

    3. 这样编码固然解决了无歧义性的问题,但是如果我们把g编码为11的话,即采用不等长编码的方式,那么其实也没有歧义的问题

    4. 歧义不歧义的根源在于,如果每个字符和其他字符的前缀编码不同,那么它们肯定就不会歧义,也就是说只要不出现a用11表示,b用110表示这种问题,就不会出现歧义

    5. 画个图表示就是下面这样

                      (0)
                   0       1
                0    1   0    1
               0 1  0 1 0 1  0  1
      

      现在最下面一层是叶结点,a是最左下角的,b是a右边的……,g放在0110处也可以,放在011处也可以,因为放在哪都不会挡到其他字符的路径

    另外这也说明了根节点的那个0是一个伪结点,它是永远不会用来编码字符的,因为只要放上去就会挡到其他字符

    1. 所以现在的需求就是:如果能让出现次数多的字符尽可能出现在靠近根结点的位置,那么编码这样的字符占用的位数就少,文件的总空间就小;另外就是注意不要让不同的字符有共同前缀,一定不要让一个字符挡到其他字符的编码路径

    2. 于是, Huffman提出了一种算法,还是用刚才的例子,首先让出现次数多的字符放在离根结点近的位置,也就是说出现次数少的字符放在离根结点远的位置;在没有用算法之前,所有字符各自是一个结点(一棵光杆二叉树),构成一个森林

    3. 现在取出权值最小的两个结点,设置一个空结点,然后让这两个结点构成空结点的左右子树(设置空结点的原因还是为了不要挡到路径上的字符);然后它们生成了一个新树,它们的联盟权值是1+2=3

            null
          1      2
      
    4. 然后让3,3,4,5,6,7这6颗树同台竞技,还是按照8的套路,现在这颗联盟树的权值变成6了,现在是4,5,6,6,7同台竞技

                null
              null    3
            1     2
      
    5.     null                 null           6       7
         4    5             null    3
                          1     2
      

    6,6,7,9同台竞技

                null               null          7
              null   6            4    5
            null  3
          1     2
    

    7,9,12同台竞技

                null                     null 
              null   6                 null   7
            null  3                   4    5
          1     2
    

    12,16同台竞技

                          null
                    null        null 
                null    6   null    7
            null    3      4    5
          1     2
    
    1. 现在搞定了,a:0000, b:0001, c:001, d:100, e:101, f:01, g:11
      总共占用41+42+33+34+35+26+2*7 = 74bit(这个数也叫__带权路径长度__)

    2. 总结下来就是,靠__不定长编码__节省了空间,并且靠__不同前缀__保证了非歧义性,同时Huffman又证明了这样生成的确实是最优二叉树

猜你喜欢

转载自blog.csdn.net/captxb/article/details/88073654