Garsia–Wachs 算法
简介
Garsia–Wachs 算法(Garsia–Wachs Algorithm)是计算机用来在 线性时间 内构建 最优二叉查找树 和 字母霍夫曼码 的有效算法。它以 Adriano Garsia 和 Michelle L. Wachs 的名字命名,他们于 1977 年发表了相关论文。
问题描述
一个整数
最优二叉查找树
这个问题可以理解为
字母霍夫曼码
这个问题也可以用作构建霍夫曼码。这是一种通过使用二进制值的可变长度序列明确编码
过程
Garsia–Wachs 算法一般包括三个阶段:
- 构建一个值位于叶子的二叉树,注意顺序可能错误。
- 计算树中根到每个叶子的距离。
- 构建另一个二叉树,叶子的距离相同,但顺序正确。
如上图所示,在算法的第一阶段,通过查找合并输入序列的无序三元组构建的二叉树(左侧),和算法输出的正确排序的二叉树,其中叶子高度与另一棵树一样。
如果输入在序列的开始和结束处增加了两个标记值
第一阶段维护了一个由最初为每个非标志(non-sentinel)输入权重创建的单节点树组成的森林。每棵树都与一个值相关联,其叶子的权重之和为每个非标志输入权重构成一个树节点。为了维护这些值的序列,每端会有两个标记值。初始序列只是叶权重作为输入的顺序。然后重复执行以下步骤,每一步都减少输入序列的长度,直到只有一棵树包含了所有叶子:
- 在序列中找到前三个连续的权重值
, , 使得 。因为序列结尾的标志值大于之前的任意两个有限值,所以总是存在这样的三元组。 - 从序列中移除
和 ,并创建一个新的树节点作为 和 节点的父节点,值为 。 - 在原来
的位置以前大于或等于 且距 最近的值的右边重新插入新节点。因为左标志值的存在,所以总是存在这样的位置。
为了有效地实现这一阶段,该算法可以在任何平衡二叉查找树结构中维护当前值序列。这样的结构允许我们在对数时间内移除
Garsia–Wachs 算法的第三阶段的证明,即存在另一棵具有相同距离的树并且这棵树提供了问题的最优解,是很重要的。但是由于其证明方式有多种且过于复杂,此处略去。在第三阶段为正确的前提下,第二和第三阶段很容易在线性时间内实现。因此,在长度为
应用
函数性编程语言 Haskell 的 garsia-wachs package 对 Garsia–Wachs 算法做了函数性实现。它主要用于构建最佳搜索表,或者以最优复杂度平衡 rope 数据结构。
注释
rope 是 Haskell 语言中用于操作带有可选注释的字节串(bytestring)手指树 的工具。
例题
POJ 1738 An old Stone Game
有一个古老的石头游戏。在游戏开始时,玩家将
解题思路
石子合并的题目很经典,一般我们可以用区间 DP 解答,但是当数据量很大,例如此题中的
ATCODER N-Slimes
参考资料与拓展阅读
- Garsia–Wachs algorithm - Wikipedia
- Data.Algorithm.GarsiaWachs - Hackage Haskell
- garsia-wachs: A Functional Implementation of the Garsia-Wachs Algorithm
- Sentinel value - Wikipedia
- A new proof of the Garsia-Wachs algorithm
本页面最近更新:2023/8/3 09:52:56,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:Enter-tainer, F1shAndCat, iamtwz, isdanni, shuzhouliu, Tiphereth-A
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用