递归(上)

中国大学MOOC,数据结构与算法(Python版)学习笔记
课程网址:“https://www.icourse163.org/course/PKU-1206307812

什么是递归

递归是一种解决问题的方法,其精髓在于将问题分解为规模更小的相同问题,持续分解,直到问题规模小到可以用非常简单直接的方式来解决。
递归的问题分解方式非常独特,其算法方面的明显特征就是:在算法流程中调用自身。递归为我们提供了一种对复杂问题的优雅解决方案,精妙的递归算法常会出奇简单,令人赞叹。

初识递归:数列求和

只是一个很简单的问题:给定一个列表,返回所有数的和。列表中数的个数不定,如果用一个循环和一个累加变量来迭代求和也很简单:

def listsum(numList):
    theSum = 0
    for i in numList:
        theSum = theSum + i
    return theSum
print(listsum([1, 3, 2, 4, 6]))

如果不用循环可以怎么求解这个问题?
求和实际上是由一次次的两数相加实现的,所以可以使用递归方式实现数列求和的问题:
数列的和=“首个数”+“余下数列”的和;如果数列包含的数少到只有1个的话,它的和就是这个数了。

def listSum(numList):
    if len(numList) == 1:
        return numList[0]
    else:
        return numList[0] + listSum(numList[1:])

print(listSum([1, 3, 2, 4, 6]))

数列求和问题首先具备了基本结束条件:当列表长度为1的时候,直接输出所包含的唯一数。
数列求和处理的数据对象是一个列表,而基本结束条件是长度为1的列表,那递归算法就要改变列表并向长度为1的状态演进,其具体做法是将列表长度减少1。调用自身是递归算法中最难理解的部分,实际上我们理解为“问题分解成了规模更小的相同问题”就可以了,在数列求和算法中就是“更短数列的求和问题”。

递归算法的要点

  1. 递归算法必须有一个基本结束条件(最小规模问题的直接解决)
  2. 递归算法必须能改变状态向基本结束条件演进(减小问题规模)
  3. 递归算法必须调用自身(解决减小了规模的相同问题)

递归算法的应用——进制转换

我们用最熟悉的十进制分析这个问题:十进制有十个不同符号: c o n v S t r i n g = “ 0123456789 ” convString = “0123456789” convString=0123456789,比十小的整数,转换成十进制,直接查表就可以了: c o n v S t r i n g [ n ] convString[n] convString[n];比十大的整数:想办法把比十大的整数,拆成一系列比十小的整数,然后逐个查表,比如七百六十九,拆成七、六、九,查表得到769就可以了。
所以 ,我们已经找到了“基本结束条件”,就是小于十的整数拆解整数的过程就是向“基本结束条件”演进的过程;我们用"整数除" ,和"求余数"两个计算来将整数一步步拆开,除以“进制基base”(// base)对“进制基”求余数(% base)。
问题就分解为:余数总小于“进制基base”,是“基本结束条件”,可直接进行查表转换整数商成为“更小规模”问题,通过递归调用自身解决

def toStr(n, base):
    converString = "0123456789ABCDEF"
    if n < base:
        return converString[n]  # 最小规模
    else:
        return toStr(n//base, base) + converString[n%base]  # 减小规模,调用自身
    
print(toStr(1453, 16))

递归调用的实现

当一个函数被调用的时候,系统会把调用时的现场数据压入到系统调用栈;每次调用,压入栈的现场数据称为栈帧;当函数返回时,要从调用栈的栈顶取得返回地址,恢复现场,弹出栈帧,按地址返回。
在这里插入图片描述

Python中的递归深度限制

在调试递归算法程序的时候经常会碰到这样的错误:RecursionError,即递归的层数太多,系统调用栈容量有限。
这时候要检查程序中是否忘记设置基本结束条件,导致无限递归或者向基本结束条件演进太慢,导致递归层数太多,调用栈溢出。
在Python内置的sys模块可以获取和调整最大递归深度:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值