zoukankan      html  css  js  c++  java
  • 「字符串学习笔记」

    Huffman树

    严格意义上来说不算是字符串的内容,但是还是放在这里讲了。

    一个很简单的模型,用来解决最优编码问题。

    这个模型非常好理解,证明也非常显然,这里主要记录一下由 (2)( ext{Huffman}) 树推广到 (k)( ext{Huffman}) 树的过程。

    下述证明约定,字符 (x) 的频率为 (f(x))

    为了推广结论,我们需要证明两个性质:

    • 贪心法选择,即最优解被包含在子问题的最优解中:设 (x_1,x_2..x_k) 是加权字符集 (C) 中频率最小的 (k) 个字母,则这 (k) 个字符在最优编码树中对应的节点必有共同的父亲。
    • 最优子结构:设 (T) 是加权字符集 (C) 的最优编码树,(x_1,x_2..x_k) 是树中 (k) 个叶子,且这 (k) 个叶子互为兄弟节点,(fa) 为他们的父节点,若把 (fa) 看作具有频率为 (sum_{i=1}^kf(x_i)) 的字符,则树 (T'=T-{x_1,x_2,..x_k}) 是字符集 (C'=C-{x_1,x_2,..x_k}igcup fa) 的最优编码树。

    首先来证明第一个性质,若存在 (y_1,y_2,..y_k) 为加权字符集 (C) 的编码树 (T) 上深度最大的节点,不妨设(f(y_1)leq f(y_2)leq..f(y_k),f(x_1)leq f(x_2)leq..f(x_k)),则 (f(x_1)leq f(y_1),f(x_2)leq(y_2)..,f(x_k)leq f(y_k)),若分别交换((x_1,y_1),(x_2,y_2)..(x_k,y_k))后解也不会变得更差,于是得证。

    第二个性质更加容易证明,设 (T') 的编码长度为 (L'),其中 ({x_1,x_2..x_k}) 的深度为 (h),那么 (T) 的编码长度为 (L=L'-h imessum_{i=1}^kf(x_i)+sum_{i=1}^k(h+1) imes f(x_i)=L'+sum_{i=1}^kf(x_i)),由于(sum_{i=1}^kf(x_i)) 为定值,所以当且仅当 (T') 最优时,(T) 是最优编码树。

    于是 (2)( ext{Huffman}) 树的解法就推广到了 (k)( ext{Huffman}) 树,但是需要注意一点,由于 (k)( ext{Huffman}) 树在深度为 (2) 时,对于一些带权字符集 (C) ,不一定能够取满 (k) 叉,因此可能取不到最优解。我们可以在叶子节点处补若干个 (f) 值为 (0) 的节点,令其能够取满。这里给出一个结论,当叶子节点数 (n) 满足 ((n-1) mod (k-1)=0) 时,必然在深度为 (2) 时能够取满 (k) 叉,也就能取到最优解。

    证明也非常简单,对于一个 (k) 叉的最优 ( ext{Huffman}) 树(在深度为 (2) 时能够取满),设其 (k) 度节点数为 (n),叶节点数目为 (m),则有 (k imes n) 条边。自然得到 (k imes n = N-1,m+n=N),联立可得 ((k-1) imes n=m-1),于是有 ((m-1)mod (k-1))注意,此处的 (m) 为叶子节点数,也就是上文的 (n)

    于是,(k)( ext{Huffman}) 树的求解就分为以下几个部分:

    • 添加 (f) 值为 (0) 的叶子节点,令建立出的 ( ext{Huffman}) 树一定是最优的。
    • 仿照 (2)( ext{Huffman}) 树的解法,每次从堆中取出 (f) 值最小的 (k) 个节点,将他们的 (f) 值累加,作为新节点重新放入堆中,直到堆的大小为 (k),这个过程中在答案上每次累加这 (k) 个节点的 (f) 值。
    • 最后的答案就是整个 ( ext{Huffman}) 树对应的最小编码长度,可以根据上述过程建出 ( ext{Huffman}) 树并求出每个字母对应的编码。

    有一个很松的上界 (O((frac{n}{k}+n) log (frac{n}{k}+n)) approx O(2n log 2n)),由于此类问题中 (k) 一般非常小,所以可忽略 (k) 对时间复杂度的影响。

  • 相关阅读:
    人脸识别算法初次了解
    白话经典算法系列之二 直接插入排序的三种实现
    常见浏览器兼容性问题与解决方式
    MP3的频率、比特率、码率与音质的关系
    程序猿接私活经验总结,来自csdn论坛语录
    Java虚拟机工作原理具体解释
    簡單SQL存儲過程實例
    全栈JavaScript之路(七)学习 Comment 类型节点.
    strdup函数的使用方法
    POJ 2823 Sliding Window 【单调队列】
  • 原文地址:https://www.cnblogs.com/tommy0103/p/12995135.html
Copyright © 2011-2022 走看看