• 13.赫夫曼树及其应用


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

        
       由图A可知。该树的带权路径长度WPL=1*10+2*70+3*15+3*5=210.
    6.赫夫曼树的建立(算法描写叙述)
    (1)依据给定的n个权值{w1,w2,....,wn}构成n棵二叉树的集合F={T1,T2,...,Tn},当中每棵二叉树T1中仅仅有一个带权为w1根结点,其左右子树均为空;
    (2)在F中选择两棵根结点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为左右子树上根结点的权值之和;
    (3)在F中删除这两棵树,同一时候将新得到的二叉树增加F中。
    (4)反复2和3步骤,直到F仅仅含一棵树为止,该树即为赫夫曼树。

    7.赫夫曼树的建立举例 
        如果有一个有序序列{A5、B15、C40、D30、E10},构成的二叉树例如以下:
    第一步:先把有权值的叶子结点依照从小到大的顺序排列成一个有序序列,即A5、E10、B15、D30、C40

    第二步:取头两个最小权值的结点作为一个新结点N1的两个孩子。相对较小的是左孩子。新结点的权值为两个叶子权值的和。例如以下图:


    第三步:将N1替换A和E,新序列为:N115,B15,D30,C40。

    第四步:反复步骤2,将N1与B作为新结点N2的两个孩子。N2的权值为15+15=30。例如以下图:


    第五步:将N2替换N1和B,新序列为:N230,D30,C40。

    第六步:反复步骤2。将N2和D作为新结点N3的两个孩子。N3的权值为30+30=60,例如以下图:


    第七步:将N3替换N2和D,新序列为:C40。N360。

    第八步:反复步骤2,将C与N3作为新结点T的两个孩子。T是根节点。至此完毕赫夫曼树的构造。例如以下图:


        图中的二叉树的WPL = 40*1 + 30*2 + 15*3 + 10*4 + 5*4 = 205。经过上面步骤构造出来的二叉树就是最优的赫夫曼树。

    二、赫夫曼编码

    1.定义

        如果须要编码的字符集为{d1,d2,...dn},各个字符在电文中出现的次数或频率集合为{w1,w2,...,wn},以d1,d2,...,dn作为叶子结点。以w1,w2,...,wn作为相应叶子结点的权值构造一棵赫夫曼树。规定:赫夫曼树的左分支代表0,右分支代表1,则从根结点到叶子结点所经过的路径分支组成的0和1的序列便为该结点相应字符的编码,这就是赫夫曼编码。

    2.举例:构造赫夫曼树进行压缩编码
        赫夫曼在研究这样的最优二叉树时的主要目的是解决当年远距离通信(主要是电报)的传输数据的最优化问题。比方传输一串字符“BADCADFEED”。採用二进制数据表示,例如以下表:

    字母

    A

    B

    C

    D

    E

    F

    二进制字符

    000

    001

    010

    011

    100

    101

    编码之后的二进制数据流为“001000011010000011101100100011”。对方接收时相同依照3位一组解码。

    如今如果这6个字母出现的频率不同,A 27%。B %8。C 15%。D 15%。E 30%,F 5%。

    以下将27、8、15、15、30、5分别作为A、B、C、D、E、F的权值构造赫夫曼树。例如以下图:


    将该图(图B)中赫夫曼树的权值左分支改为0。右分支改为1。例如以下图C:

     

    如今将这6个字母用从根节点到叶子所经过路径的0或1来编码,得到的编码表例如以下:

    字母

    A

    B

    C

    D

    E

    F

    二进制字符

    01

    1001

    101

    00

    11

    1000

    将“BADCADFEED”再次编码得到“1001010010101001000111100”。共25个字符。与之前编码得到的30个字符相比大约节约了17%的存储和传输成本。 

    在解码时,用相同的赫夫曼树。即发送方和接收方约定好相同的赫夫曼编码规则。当接收方接收到“1001010010101001000111100”时,比对图C中的赫夫曼树。由1001正好走到字母B,例如以下图:

    然后是01,则从根结点走到字母A,例如以下图:


        其余的字母也可对应成功解码。



  • 相关阅读:
    Intent
    BroadcastReceiver
    AsyncTask两种线程池
    多线程、Service与IntentService的比较
    AsyncTask
    转:Android开发:使用DDMS Heap进行内存泄露调试
    (原创)Android Binder设计与实现
    (原)一句mpAudioPolicy->get_input引发的血案
    LOCAL_WHOLE_STATIC_LIBRARIES与LOCAL_STATIC_LIBRARIES的区别
    非static成员函数通过类名::来调用,空指针调用成员方法不出错!
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7298001.html
Copyright © 2020-2023  润新知