汉诺塔问题介绍

汉诺塔是一个源于印度古老传说的益智问题。有三根柱子(假设分别为A柱、B柱、C柱 ),A柱上从下往上按照大小顺序摞着若干个圆盘。游戏目标是把A柱上的圆盘按同样大小顺序重新摆放到C柱上,并且规定:

  • 每次只能移动一个圆盘。
  • 在小圆盘上不能放大圆盘,即任何时刻大圆盘不能压在小圆盘上面。
  • 可以借助B柱来辅助移动圆盘。

代码实现思路

可以使用递归的方法来解决汉诺塔问题。递归就是函数自己调用自己。基本思路如下:

  • n - 1 个圆盘从A柱借助C柱移动到B柱 (这是一个子问题,规模变小了 )。
  • 把第 n 个(也就是最下面最大的 )圆盘从A柱直接移动到C柱。
  • 再把B柱上的 n - 1 个圆盘借助A柱移动到C柱 (又是一个类似的子问题 )。

Python代码及注释

def hanoi(n, source, target, auxiliary):
    """
    汉诺塔递归函数
    :param n: 圆盘的个数
    :param source: 源柱子(开始时圆盘所在柱子)
    :param target: 目标柱子(最终圆盘要移动到的柱子)
    :param auxiliary: 辅助柱子(用来辅助移动圆盘的柱子)
    """
    if n == 1:
        # 当只有一个圆盘时,直接从源柱子移动到目标柱子
        print(f"Move disk 1 from {source} to {target}")
        return
    # 把n - 1个圆盘从源柱子借助目标柱子移动到辅助柱子
    hanoi(n - 1, source, auxiliary, target)
    print(f"Move disk {n} from {source} to {target}")
    # 把n - 1个圆盘从辅助柱子借助源柱子移动到目标柱子
    hanoi(n - 1, auxiliary, target, source)

代码调用示例

# 假设有3个圆盘,A柱为源柱子,C柱为目标柱子,B柱为辅助柱子
hanoi(3, 'A', 'C', 'B') 

代码解释

  • 函数 hanoi 定义了汉诺塔问题的解决逻辑。它接收4个参数,n 代表圆盘数量,source 是起始柱子,target 是目标柱子,auxiliary 是辅助柱子。
  • n == 1 时,这是递归的终止条件,因为只有一个圆盘,直接把它从源柱子移动到目标柱子并打印移动步骤即可。
  • 对于 n > 1 的情况,先递归调用 hanoi 函数把 n - 1 个圆盘从源柱子借助目标柱子移动到辅助柱子,然后打印把第 n 个圆盘从源柱子移动到目标柱子的步骤,最后再递归调用 hanoi 函数把辅助柱子上的 n - 1 个圆盘借助源柱子移动到目标柱子。

这样,通过递归的方式就可以解决汉诺塔问题,并且打印出每一步的移动操作。

4 条评论

  • @ 2025-4-9 20:21:30
    def hanoi(n, source, target, auxiliary):
        """
        汉诺塔递归函数
        :param n: 圆盘的个数
        :param source: 源柱子(开始时圆盘所在柱子)
        :param target: 目标柱子(最终圆盘要移动到的柱子)
        :param auxiliary: 辅助柱子(用来辅助移动圆盘的柱子)
        """
        if n == 1:
            # 当只有一个圆盘时,直接从源柱子移动到目标柱子
            print(f"将 1 号盘从 {source} 到 {target}")
            return
        # 把n - 1个圆盘从源柱子借助目标柱子移动到辅助柱子
        hanoi(n - 1, source, auxiliary, target)
        print(f"将 {n} 号盘从 {source} 到 {target}")
        # 把n - 1个圆盘从辅助柱子借助源柱子移动到目标柱子
        hanoi(n - 1, auxiliary, target, source)
    
    # 假设有3个圆盘,A柱为源柱子,C柱为目标柱子,B柱为辅助柱子
    #hanoi(3, 'A', 'C', 'B')
    hanoi(3, '第一个柱子', '第三个柱子', '第二个柱子')
    
    • @ 2025-4-9 19:43:51

      • @ 2025-4-9 19:26:00

        汉诺塔问题概述

        汉诺塔问题是一个经典的递归问题,有三根柱子(通常标记为A、B、C),在柱子A上有若干个大小不同的圆盘,要求把这些圆盘从柱子A移动到柱子C,且移动过程需遵循以下规则:

        1. 每次只能移动一个圆盘。
        2. 任何时候大圆盘都不能放在小圆盘上面。

        递推关系分析

        设移动 n 个圆盘所需的最少步数为 T(n)T(n)

        • 初始情况:当 n=1n = 1 时,只需要将这一个圆盘从起始柱直接移动到目标柱,所以 T(1)=1T(1)=1
        • 递推情况:当有 nn 个圆盘时,可以把移动过程分为三个步骤:
          1. 把上面的 n1n - 1 个圆盘从起始柱借助目标柱移动到辅助柱,这一步需要的步数是 T(n1)T(n - 1)
          2. 把最下面的第 nn 个圆盘从起始柱移动到目标柱,这一步需要 11 步。
          3. 把辅助柱上的 n1n - 1 个圆盘借助起始柱移动到目标柱,这一步又需要 T(n1)T(n - 1) 步。

        因此,得到递推公式 T(n)=2T(n1)+1T(n)=2T(n - 1)+1

        通项公式推导

        对递推公式 T(n)=2T(n1)+1T(n)=2T(n - 1)+1 进行变形求解通项公式:

        • T(n)+x=2(T(n1)+x)T(n)+x = 2(T(n - 1)+x),展开可得 T(n)=2T(n1)+xT(n)=2T(n - 1)+x
        • 对比 T(n)=2T(n1)+1T(n)=2T(n - 1)+1,可知 x=1x = 1
        • 那么数列 {T(n)+1}\{T(n)+1\} 是以 T(1)+1=2T(1)+1 = 2 为首项,22 为公比的等比数列。
        • 根据等比数列通项公式 an=a1qn1a_n=a_1q^{n - 1}(这里 an=T(n)+1a_n=T(n)+1a1=2a_1 = 2q=2q = 2),可得 T(n)+1=2×2n1=2nT(n)+1=2\times2^{n - 1}=2^n
        • 所以,T(n)=2n1T(n)=2^n - 1

        Python 代码实现

        下面是用 Python 实现根据通项公式计算移动 n 个圆盘所需最少步数的代码:

        # 定义一个函数,接收圆盘数量 n 作为参数
        def hanoi_steps(n):
            # 根据通项公式 2^n - 1 计算移动 n 个圆盘所需的最少步数
            return 2 ** n - 1
        
        # 示例:计算移动 3 个圆盘所需的最少步数
        n = 3
        # 调用函数计算结果
        steps = hanoi_steps(n)
        print(f"移动 {n} 个圆盘最少需要 {steps} 步。")
        
        

        代码解释

        • hanoi_steps 函数接收一个整数参数 n,代表圆盘的数量。
        • 在函数内部,使用 2 ** n - 1 计算移动 n 个圆盘所需的最少步数,其中 2 ** n 表示 2 的 n 次方。
        • 最后通过示例,计算并输出移动 3 个圆盘所需的最少步数。你可以修改 n 的值来计算不同数量圆盘的最少移动步数。
        • 1