树--哈夫曼树

    前面章节分别学习了树、森林与二叉树的转换、线索二叉树、树、二叉树的基本知识。本节接着学习"哈夫曼树"

     在复杂的if...else或switch...case语句中,判断的次序影响程序执行时间。之前学习过,凡是在某个点有两种互斥结果的均可以使用二叉树来表示。而最优的表示法即哈夫曼表示法。原则上,它通过将最大量置顶构造出一颗"最优树",即带权路径长度最短

基本概念

    路径:节点之间的连线

    节点的路径长度:节点之间连线的个数(路径的个数)

    树的路径长度:树根到每个节点的路径和,相同节点数的二叉树,完全二叉树的路径长度最短

    权:节点的标识,一般为可计算的数学标识

    节点的带权路径长度:根节点到该节点之间的路径长度与目标节点权值的乘积

    树的带权路径长度:树中所有叶子节点的带权路径长度

    n个叶子节点的哈夫曼树有2n-1个节点,需经过n-1次合并,将产生n-1个新节点,每个节点的度都不为

    1。所构建的哈夫曼树的层级为n-1

构造哈夫曼树

    构造过程(哈夫曼树中权值越大离根越近)

        构造森林,每一颗树都是以权值为根构造的单点树

        构造一颗新二叉树,其左右子树根为最小权值树,该二叉树的根的权值为左右子树根权值的和,              并从森林中删除对应的树

        将二叉树作为森林的成员

    图示如下

        假设有如下一组值,它们代表节点的权值

            [1,3,4,5,8]

        构造森林如下,该森林由一颗颗只有一个根节点的树组成

        构建一颗二叉树,其左右子树根从森林中挑选最小的两个,该颗二叉树的根节点的权值=挑选的权

        值和

         从森林中删除挑选出的两颗树,并将构造的新二叉树入森林,此时森林如下

        继续挑选最小的两颗树,并据此构建一颗二叉树,即

        继续将新二叉树入队森林,并剔除挑选的树,此时森林如下

            重复以上步骤,即挑选5和8组成新二叉树,即

            此时森林如下

            继续以上两部,则最终生成的树如下

    JavaScript实现如下

        由于n个叶子节点的哈夫曼树有2n-1个节点,故对于数组[1,3,4,5,8]的数组大小为9

        节点结构如下

(data为了每次挑选方便增加)

        代码实现如下

            为了方便挑选最小值,先对数组进行一次排序,即

            构建一个具有2n-1个成员的数组,并初始化

            每次从数组中挑选最小的两颗树并构建一颗二叉树,根的权重为挑选的权值和,挑选的树分别

                视为二叉树的左右子树根

            生成的哈夫曼树如下

            完整实现算法如下

哈夫曼编码

    数据的传输是先将数据转换成二进制0和1之后传到目的地后解码,数据量越小传输效率越大。在同样的待传数据中,如何做到最小,正是哈夫曼编码解决的问题

    哈夫曼编码的理论基础为前缀编码,由于叶子节点的特性保证了其不可能为另一叶子节点的双亲,故其任一字符的编码均不是令一字符编码的前缀

    哈夫曼编码的规则如下

        对数据进行概率分析,得到某个字符出现的次数

            若有串"aabca",则a的概率为3,b为1,c为1

        将概率作为权值构造哈夫曼树,在构建过程中生成的二叉树将其路径标记为0右1

        从哈夫曼树的根节点到叶子节点的路径标记作为字符编码,则

            a:0  b:10 c:11

    JavaScript实现如下

        假设有字符串:'abcaabac',则计算的每个字符出现的频率如下

    得到的哈夫曼树如下

    从叶子节点向上查找,按照左0右1标记路径直到哈夫曼树的根,则为该叶子节点的哈夫曼编码。算

        法实现如下

         结果如下

    

你可能感兴趣的:(树--哈夫曼树)