Python for Kids
  • 0 前言
  • 1 编程环境准备
  • 2 运算符和表达式
  • 3 掌握变量
  • 4 字符串
  • 5 获取用户的输入
  • 6 条件判断
  • 7 条件判断实操
  • 8 FOR循环
  • 9 循环和列表
  • 10 WHILE循环
  • 11 WHILE循环实操
  • 12 WHILE循环再实操
  • 13 多重循环
  • 14 再谈列表
  • 15 初见函数
  • 16 函数实操
  • 17 选择排序
  • 18 冒泡排序
  • 19 递归算法之一
  • 20 递归算法实操
  • 21 快速排序
  • 22 汉诺塔游戏
  • 23 递推算法
  • 24 分治算法
  • 25 集合与组合
  • 26 贪心算法
  • 27 字典和键值对
  • 28 广度优先搜索算法
  • 29 数组和向量化计算
  • 30 随机和模拟
  • 31 数据可视化
  • 32 文件读取和分析
Powered by GitBook
On this page
  • 大纲
  • 什么是递归算法
  • 用递归来求和
  • 用递归来找最大值
  • 用递归来计算阶乘

Was this helpful?

19 递归算法之一

递归是最奇妙的思想

大纲

  • 什么是递归算法

  • 用递归来求和

  • 用递归来找最大值

  • 用递归来计算阶乘

什么是递归算法

大家都听过这个故事吧:从前有座山,山上有座庙,庙里有个老和尚,老和尚在讲故事给小和尚听:从前有座山,山上有座庙,庙里有个老和尚,老和尚在讲故事给小和尚听:从前座山,山上有座庙,庙里有个老和尚,老和尚在讲故事给小和尚听………

story = '从前有座山,山上有座庙,庙里有个老和尚,老和尚在讲故事给小和尚听:'
count = 0
def recursive(story=story):
    global count
    # 停止条件
    if count == 3:
        return story
    else:
        count += 1
        return story + recursive(story)
recursive()
'从前有座山,山上有座庙,庙里有个老和尚,老和尚在讲故事给小和尚听:从前有座山,山上有座庙,庙里有个老和尚,老和尚在讲故事给小和尚听:从前有座山,山上有座庙,庙里有个老和尚,老和尚在讲故事给小和尚听:从前有座山,山上有座庙,庙里有个老和尚,老和尚在讲故事给小和尚听:'

在上面这个函数里,它自己调用了自己,最后拼接出了一个嵌套的故事。

用递归来求和

直观上理解,递归是函数套函数,自己调用自己。递归是一种优雅的算法思想,刚接触递归的时候可能不大容易理解,我们先用一个具体的例子来看一下。例如计算一个列表求和值。可以直接用循环来完成。

def sum_list(x):
    total = 0
    for value in x:
        total = total + value
    return total
sum_list([14,6,7,4,9,30])
70

让我们换个思路,考虑极端情况,如果一个列表里只有一个值,那么求和就是它本身,如果一个列表中再多一个值,就把两个值相加。

def sum_recursion(x):
    print(x)  
    if len(x) == 1:  # 极端条件或者是停止条件
        return x[0]
    else:
        return x[0] + sum_recursion(x[1:]) #不满足条件则进行分拆,同时调用自身

sum_recursion([14,6,7,4,9,30])
[14, 6, 7, 4, 9, 30]
[6, 7, 4, 9, 30]
[7, 4, 9, 30]
[4, 9, 30]
[9, 30]
[30]





70

让我们来理解了下上面的代码,为了理解方便,我们在函数的开始去打印输入列表x,在一开始的时候这是有六个数字元素的完整列表,然后进入条件判断,如果这个列表只有一个值,就是出现了极端情况,直接输出这个值,如果不满足条件,说明列表中有多个值,我们就把当前状态的x进行分拆。

分拆思路是这样的,把第一个位置的数字拿出来,再去求和函数去求剩下数字的和。此时函数还没有计算完,程序会暂停住,去计算里面那个调用自身的函数。可以注意到这里函数内部又再次调用了自身,这就是递归的不同之处,因为列表有6个数字,所以它反复调用自己到第6次的时候,才发现满足len(x)等于1的条件,输出了30,然后回到第5次调用函数的时候,将30和9相加,再回到第4次调用函数的时候,39和4相加,以此类推,回到最外层函数,得到最终70的答案。

如果你看过电影盗梦空间的话,递归这种自己调用自己的作法就好像进入不同的梦境,只有在最底层梦境满足极端条件的时候,才会真正算出一个值,同时依次返回上次梦境,得到最终的答案。

所以我们总结一下写递归函数的几个要点:

  • 需要明确这个函数的目的

  • 函数中的终止条件是什么

  • 函数中的分拆方法是什么

用递归来找最大值

前面的课程我们学习过,使用循环可以找最大值

x = [31, 2,101, 23, 28, 65, 7]
def find_max(x):
    x_max = x[0]
    for i in x:
        if x_max<i:
            x_max = i
    return x_max
find_max(x)
101

下面我们来模仿之前的例子来用递归实现一下。

def find_max_recursion(x):
    print(x)
    if len(x) <2:  # 极端条件或者是停止条件
        return x[0]
    else:
        m = len(x)//2
        x1 = x[:m]
        x2 = x[m:]
        u = find_max_recursion(x1)
        v = find_max_recursion(x2)
        if u>v:
            return u
        else:
            return v
x = [31, 2,101, 23, 28, 65, 7]
find_max_recursion(x)
[31, 2, 101, 23, 28, 65, 7]
[31, 2, 101]
[31]
[2, 101]
[2]
[101]
[23, 28, 65, 7]
[23, 28]
[23]
[28]
[65, 7]
[65]
[7]





101

用递归来计算阶乘

再看一个递归用来计算阶乘的例子,3!表示计算3的阶乘,也就是等于3,2,1相乘

def fac_Recursionr(x):
    print(x)
    if x == 1:
        return 1
    else:
        return x * fac_Recursionr(x-1)

fac_Recursionr(4)
4
3
2
1





24

同样用来调试理解方便,这里将x打印了出来。先判断是否满足极端条件,如果x等于1,那么它的阶乘就是1,如果不满足极端状态,我们就要把x进行分拆,将它往极端情况去推,同时考虑当前状态和缩减状态的关系是一个乘法的关系。

小结:递归算法会在函数中调用自己,通常先会有一个条件判断,判断输入是否满足极端状态,如果满足则直接得到解,如果不满足极端状态,就要把输入问题进行分拆,分拆成更小的子问题,将它往极端状态去推,同时考虑当前状态和缩减后状态的关系。

Previous18 冒泡排序Next20 递归算法实操

Last updated 4 years ago

Was this helpful?