Update 算法 - 其它.md

调整汉诺塔递归步骤与移动次数的推导说明,补充哈夫曼编码长度对比及解码特性的描述。
This commit is contained in:
CyC2018
2026-10-30 20:19:18 +08:00
parent c71675fd40
commit da2a47d4b6
+8 -6
View File
@@ -5,23 +5,23 @@
有三个柱子,分别为 from、buffer、to。需要将 from 上的圆盘全部移动到 to 上,并且要保证小圆盘始终在大圆盘上。
这是一个经典的递归问题,分为三步求解:
这是一个经典的递归问题。如果只有一个圆盘,直接从 from 移到 to;有 n 个圆盘时分为三步:
① 将 n-1 个圆盘从 from -\> buffer
第一步,借助 to,将上面的 n - 1 个圆盘从 from 移到 buffer。
<div align="center"> <img src="pics/hanoi-step1.png" width="460px"/> </div><br>
② 将 1 个圆盘从 from -\> to
第二步,将最大的圆盘从 from 移到 to。
<div align="center"> <img src="pics/hanoi-step2.png" width="460px"/> </div><br>
③ 将 n-1 个圆盘从 buffer -\> to
第三步,借助 from,将 n - 1 个圆盘从 buffer 移到 to。
<div align="center"> <img src="pics/hanoi-step3.png" width="460px"/> </div><br>
如果只有一个圆盘,那么只需要进行一次移动操作。
“借助”的柱子就是递归调用中的 buffer 参数,因此代码中第一步和第三步调用 move() 时交换了参数的顺序。
从上面的讨论可以知道,a<sub>n</sub> = 2 * a<sub>n-1</sub> + 1,显然 a<sub>n</sub> = 2<sup>n</sup> - 1,n 个圆盘需要移动 2<sup>n</sup> - 1 次。
设 n 个圆盘需要移动 a<sub>n</sub> 次,由三个步骤得到 a<sub>n</sub> = 2a<sub>n-1</sub> + 1,a<sub>1</sub> = 1。两边加 1 得到 a<sub>n</sub> + 1 = 2(a<sub>n-1</sub> + 1),因此 a<sub>n</sub> = 2<sup>n</sup> - 1,例如 3 个圆盘需要移动 7 次。
```java
public class Hanoi {
@@ -68,6 +68,8 @@ from H1 to H3
生成编码时,从根节点出发,向左遍历则添加二进制位 0,向右则添加二进制位 1,直到遍历到叶子节点,叶子节点代表的字符的编码就是这个路径编码。
上面的例子按下图编码,总长度为 250 位,每个字符固定 2 位则需要 300 位。因为字符都在叶子节点上,任何一个编码都不是另一个编码的前缀,解码时从根节点按位走到叶子节点就得到一个字符,不需要分隔符。
<div align="center"> <img src="pics/huffman-tree.png" width="620px"/> </div><br>
```java