Python入门之经典函数实例——第1关:递归函数 - 汉诺塔的魅力

Posted YLeee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python入门之经典函数实例——第1关:递归函数 - 汉诺塔的魅力相关的知识,希望对你有一定的参考价值。

任务描述

在Python函数内部,我们可以去调用其他函数。所以如果一个函数在内部调用自身,这个函数我们就称为递归函数。本关我们将以汉诺塔的例子来感受递归函数的方法与应用。

汉诺塔问题源于印度一个古老传说。相传大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?

本关目标就是通过对汉诺塔问题的探讨,让读者了解并掌握递归函数的相关知识。

相关知识

在编程语言中,如果一种计算过程的其中每一步都会用到前一步或前几步的结果,这个计算过程就可以称为递归的。而用递归计算过程定义的函数,则被称为递归函数。递归函数应用很广泛,例如连加、连乘及阶乘等问题都可以利用递归思想来解决。而汉诺塔问题也是递归函数的经典应用。

汉诺塔问题的解决思路:如果我们要思考每一步怎么移可能会非常复杂,但是可以将问题简化。我们可以先假设除a柱最下面的盘子之外,已经成功地将a柱上面的63个盘子移到了b柱,这时我们只要再将最下面的盘子由a柱移动到c柱即可。

当我们将最大的盘子由a柱移到c柱后,b柱上便是余下的63个盘子,a柱为空。因此现在的目标就变成了将这63个盘子由b柱移到c柱。这个问题和原来的问题完全一样,只是由a柱换为了b柱,规模由64变为了63。因此可以采用相同的方法,先将上面的62个盘子由b柱移到a柱,再将最下面的盘子移到c柱。

以此内推,再以b柱为辅助,将a柱上面的62个圆盘最上面的61个圆盘移动到b柱,并将最后一块圆盘移到c柱。

我们已经发现规律,我们每次都是以ab中一根柱子为辅助,然后先将除了最下面的圆盘之外的其他圆盘移动到辅助柱子上,再将最底下的圆盘移到c柱子上,不断重复此过程。

这个反复移动圆盘的过程就是递归,例如我们每次想解决n个圆盘的移动问题,就要先解决(n-1)个盘子进行同样操作的问题。

我们先假设a柱上只有3个圆盘,利用Python进行编程实现圆盘的移动,代码如下:

def move(n, a, b, c):
    if(n == 1):
        print(a,"->",c)
        return
    move(n-1, a, c, b)
    move(1, a, b, c)
    move(n-1, b, a, c)

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

函数运行结果:

  1. a -> c
  2. a -> b
  3. c -> b
  4. a -> c
  5. b -> a
  6. b -> c
  7. a -> c

程序分析:

首先我们定义了一个函数move(n,a,b,c),参数n代表a柱上的圆盘个数,a,b,c三个柱子的顺序代表要将a柱上的圆盘最终移动到c柱上,然后b柱作为中间柱。

我们在递归函数中肯定会有终止递归的条件,24行的代码就是表示当a柱上的圆盘个数为1的时,就中止递归并返回,因为此时a柱上面只有一个圆盘的时候肯定就是直接把圆盘从a柱移动到c柱了。

5行的代码move(n-1, a, c, b)表示先得把a柱上的n-1个圆盘从a柱移动到b柱,这时c柱是中间辅助柱。

6行的代码move(1, a, b, c)就是条件n=1的时候,表示把a柱上剩下的1个最大圆盘从a柱移动到c柱。

7行的代码move(n-1, b, a, c)表示现在n-1个圆盘转移到要b柱上了,还是递归调用move函数,将n-1个圆盘从b柱移动到c柱,这时a柱是中间辅助柱。

最后我们调用move函数将3个圆盘从a柱移动到到c柱,当移动64个圆盘时,只需要将调用函数move(n,a,b,c)中的n变为64即可,这个计算量是十分巨大的,也只能交给计算机去解决。

小结:

我们通过汉诺塔的例子感受了递归函数的基本思路,并尝试解决了一个具体问题。递归函数的优点是定义清晰,思路简洁,能够极大简化编程过程。理论上,所有的递归函数都可以用循环的方法代替,但循环方法的编程过程要比递归函数复杂很多。

编程要求

本关的编程任务是补全src/step1/recursive.py文件的代码,实现相应的功能。具体要求如下:

  • 定义一个函数fact(n),实现的功能是对输入的正整数n进行n!运算。
  • 调用函数fact(n),对输入的正整数n进行阶乘运算,并输出计算结果。

测试说明

本关的测试文件是src/step1/recursive.py,测试过程如下:

  1. 平台自动编译生成recursive.exe;
  2. 平台运行recursive.exe,并以标准输入方式提供测试输入;
  3. 平台获取recursive.exe输出,并将其输出与预期输出对比。如果一致则测试通过,否则测试失败。

以下是平台对src/step1/recursive.py的样例测试集:

测试输入:
5
预期输出:
120

测试输入:
6
预期输出:
720

测试输入:
7
预期输出:
5040

测试输入:
8
预期输出:
40320

开始你的任务吧,祝你成功!

梦虽虚幻,却是自己的梦想;位虽低微,却是自己的岗位;屋虽简陋,却是自己的家;志虽渺小,却是自己的追求。

如果你觉得这一关的内容对你有帮助,请你在下面点赞。

 

参考答案

#coding=utf-8

#输入正整数n
n = int(input())

# 请在此添加代码,实现n!
#********** Begin *********#
def fact(n):
    if n == 1:
        res = 1
    else:
    	res = n * fact(n - 1)
    return res

print(fact(n))


#********** End **********#

 

以上是关于Python入门之经典函数实例——第1关:递归函数 - 汉诺塔的魅力的主要内容,如果未能解决你的问题,请参考以下文章

Python入门之经典函数实例——第2关:Lambda函数 - 匿名函数的使用

Python入门之经典函数实例——第2关:Lambda函数 - 匿名函数的使用

Python入门之经典函数实例——第3关:Map-Reduce - 映射与归约的思想

Python入门之经典函数实例——第3关:Map-Reduce - 映射与归约的思想

Python入门之函数调用——第1关:内置函数 - 让你偷懒的工具

Python入门之函数结构——第1关:函数的参数 - 搭建函数房子的砖