有人可以逐步解释此功能的作用吗 - python

def hanoi(n,f,v,t):
    if n == 0:
        pass
    else:
        hanoi(n-1,f,t,v)
        print(f"Move disc from {f} to {t}.")
        hanoi(n-1,v,f,t)

hanoi(3,"a","b","c")

我正在研究递归,无法弄清楚这个“河内之塔”功能。它工作正常,但我不知道它在做什么。例如,函数打印的指令之一是:
“将光盘从c移到b。”
但是在我看来{f}只能是“a”或“b”?
何时(n = 2)似乎很容易理解,因为它调用(n = 1)打印“将光盘从a移动到b”。
然后移回(n = 2),打印“将光盘从a移到c”。
然后它调用(n = 1),打印“将光盘从b移到c”。
但是我不明白n的较大值会发生什么。

参考方案

要了解递归,您必须首先了解递归。

Imo,将您的所有递归功能都包含在内的最好方法是写下(以书面形式,老式风格)以某种形式发生的事情。

为什么要用纸?绘制随机的东西比在计算机上容易和快捷。这很简单,但是递归比较复杂,因此将所有内容显式写出可能不切实际。在这种情况下,我喜欢象征性地总结内容,绘制图表等。

第二个最好的例子是使它打印东西。为此,让我们稍微修改一下您的初始代码。

def hanoi(n,_from,,t):
    print(f"Hanoi called: n:{n}, f:{f}, v:{v}, t:{t}")
    if n == 0:
        pass
    else:
        hanoi(n-1,f,t,v)
        print(f"Move disc from {f} to {t}. n:{n}")
        hanoi(n-1,v,f,t)

hanoi(3,"a","b","c")

输出结果:

Hanoi called: n:3, f:a, v:b, t:c (4)
Hanoi called: n:2, f:a, v:c, t:b (2)
Hanoi called: n:1, f:a, v:b, t:c (1)
Move disc from a to c. n:1       (1)
Move disc from a to b. n:2       (2)
Hanoi called: n:1, f:c, v:a, t:b (3)
Move disc from c to b. n:1       (3)
Move disc from a to c. n:3       (4)
Hanoi called: n:2, f:b, v:a, t:c (6)
Hanoi called: n:1, f:b, v:c, t:a (5)
Move disc from b to a. n:1       (5)
Move disc from b to c. n:2       (6)
Hanoi called: n:1, f:a, v:b, t:c (7)
Move disc from a to c. n:1       (7)

Process finished with exit code 0

如果您将其与此有人可以逐步解释此功能的作用吗 - python进行比较

请注意,不满足基本条件(n == 0)的第一个调用如何继续“深入”到递归中。达到基本情况后,递归将取消调用的堆栈-您从LAST递归调用中移出(n == 1,第一个移动磁盘)。然后n == 2(第二个移动磁盘)等等。

也许不是那么具有讽刺意味的是,河内的塔楼本身是一个很好的类比递归的工作方式:您实际上将调用(例如,您最终要做的事情)堆积成一大堆。然后,一旦您完成了新调用的堆叠(例如,您已经达到基本情况,此处n == 0),那么您将接听最后放入您的调用栈的所有调用并执行该调用。

编辑:我已经删除了对河内的n == 0调用(因为他们什么也没做,只会使事情变得混乱)。我在括号中添加了与图像(2),(3)等上的每个调用相对应的图像中的步骤。每个#都会出现两次-执行一次(例如,“从磁盘中移动磁盘...”),然后一次放到调用栈中(“河内叫....”)。

如您所见,当我们打给n大于1的河内电话时,其中一些电话会堆叠在一起(例如(1)(2)(4))。当我们达到n == 0时,我们将逐步将它们堆叠。因此,我们首先执行-> c,即(1),因为该调用最后被堆叠到了递归堆栈上。例如。 (4)首先添加了n == 3,但是在执行它之前,递归迫使我们堆叠另一个n == 2(2)和n == 1(1)的对象。只有到那时,我们才能开始执行对河内的积压呼叫。我们将了解为什么对河内的第一次呼叫在下面标记为(4)而不是(3)。只要确保您正确理解了第一部分。

然后我们马上执行---> b((2))。但是在那时n == 2,所以当我们对河内进行该调用时,在继续进行(4)之前,我们在堆栈(3)上添加了另一个调用。由于最后一个被添加,我们立即拆开(3)的堆栈。然后,我们剩下的唯一要从调用堆栈弹出的调用是(4)。由于其n == 3,这将使我们在递归堆栈(6)和(5)上添加更多新调用。同样,我们以相反的顺序拆开它们(因为(5)位于(6)的“顶部”)。使用(6),n == 2,因此我们将向河内添加另一个调用,将是(7)。那时,我们不再向堆栈添加调用,因此我们完全摆脱了递归。

Python uuid4,如何限制唯一字符的长度 - python

在Python中,我正在使用uuid4()方法创建唯一的字符集。但是我找不到将其限制为10或8个字符的方法。有什么办法吗?uuid4()ffc69c1b-9d87-4c19-8dac-c09ca857e3fc谢谢。 参考方案 尝试:x = uuid4() str(x)[:8] 输出:"ffc69c1b" Is there a way to…

Python:无法识别Pip命令 - python

这是我拍摄的屏幕截图。当我尝试在命令提示符下使用pip时,出现以下错误消息:pip无法识别为内部或外部命令,可操作程序或批处理文件。我已经检查了这个线程:How do I install pip on Windows?我所能找到的就是我必须将"C:\PythonX\Scripts"添加到我的类路径中,其中X代表python版本。如您在我的…

Python:如何将有效的uuid从String转换为UUID? - python

我收到的数据是 { "name": "Unknown", "parent": "Uncategorized", "uuid": "06335e84-2872-4914-8c5d-3ed07d2a2f16" }, 我需要将uuid从Strin…

Python 3会流行吗? - python

我已经学习了一些Python 2和Python 3,似乎Python 2总体上比Python 3更好。这就是我的问题所在。是否有充分的理由真正切换到python 3? 参考方案 总体上,甚至在大多数细节上,Python3都比Python2更好。关于第三方库, Python 3落后于的唯一区域是。使Python变得如此出色的原因不仅在于它作为一种语言的内在特性…

Python-如何检查Redis服务器是否可用 - python

我正在开发用于访问Redis Server的Python服务(类)。我想知道如何检查Redis Server是否正在运行。而且如果某种原因我无法连接到它。这是我的代码的一部分import redis rs = redis.Redis("localhost") print rs 它打印以下内容<redis.client.Redis o…