什么是递归函数

一种计算过程,如果其中每一步都要用到前一步或前几步的结果,称为递归的。用递归过程定义的函数,称为递归函数,例如连加、连乘及阶乘等。凡是递归的函数,都是可计算的,即能行的。

  • 递归就是一个函数在它的函数体内调用它自身。

编程语言中的对递归定义:

  • 编程语言中,函数Func(Type a,……)直接或间接调用函数本身,则该函数称为递归函数。递归函数不能定义为内联函数。

数学中对递归的定义:

  • 在数学上,关于递归函数的定义如下:对于某一函数f(x),其定义域是集合A,那么若对于A集合中的某一个值X0,其函数值f(x0)由f(f(x0))决定,那么就称f(x)为递归函数。

递归的条件:

  • 一个含直接或间接调用本函数语句的函数被称之为递归函数,在上面的例子中能够看出,它必须满足以下两个条件:

    • 1)执行递归函数将反复调用其自身,每调用一次就进入新的一层。
    • 2)必须有结束条件,即必须有一个终止处理或计算的准则。

递归函数的应用

应用一: 计算阶乘(factorial)

  • 定义:一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!

  • 任何大于等于1 的自然数n 阶乘表示方法:n! = 1*2*3* ...*(n-1)*n,或,n! = n *(n-1)!

  • 阶乘的规律:

    1! = 1
    2! = 2 × 1 = 2 × 1!
    3! = 3 × 2 × 1 = 3 × 2!
    4! = 4 × 3 × 2 × 1 = 4 × 3!
    ...
    n! = n × (n-1)!
  • 用递归函数来计算阶乘: 通过用户输入数字(n)计算阶乘

    # 获取用户输入的数字
    num = int(input("请输入一个数字: "))
    factorial = 1 # 查看数字是负数,0 或 正数
    if num < 0:
    print("抱歉,负数没有阶乘")
    elif num == 0:
    print("0 的阶乘为 1")
    else:
    for i in range(1,num + 1):
    factorial = factorial*I print("%d 的阶乘为 %d" %(num,factorial))
  • 上述代码运行结果如下:

    请输入一个数字: 3   #输入3,求3的阶乘. 3! = 3*2*1 =6
    3 的阶乘为 6

-上述递归函数的调用过程:

  • 在Python中,还可以使用循环来实现阶乘的计算:

    • 使用while循环实现计算3的阶乘
    n=4      #求4的阶乘
    result=1
    I=1
    while i<=4:
    result=result*I
    I+=1 print(result)

从上面两中方法的对比可以看出,递归函数的作用和循环的方法效果一样,即递归函数本质上是一个方法的循环调用,注意:有可能会出现死循环。因此,使用递归函数时,一定要定义递归的边界(即什么时候退出循环)。

应用二: 计算斐波那契数列 (Fibonacci sequence)

  • 斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:

    • 1,1,2,3,5,8,13,21,34,55,89,144……
    • 从3三个数开始,后一个数等于前面两个数的和
    • 在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*)

  • 用递归函数来实现获取斐波拉契数列中第n个数字的值:

    #  计算斐波那契数列第n位的值
    def fab(n):
    if n > 2:
    return fab(n-1) + fab(n-2)
    else:
    return 1 # 打印斐波那契数列
    def printfablist(n):
    for i in range(1, n+1):
    print(fab(i),end = ' ') # 传参调用
    printfablist(int(input('请输入要输出多少项:')))
  • 上述代码运行结果如下:

    请输入要输出多少项:4    #键入4,求斐波那契数列前四项
    1 1 2 3 # 得到斐波那契数列前四项
  • 同样的,除了递归函数外,还可以使用while循环来实现斐波那契数列:

    # 获取用户输入数据
    num_n = int(input("请输入你需要几项:")) # 第一和第二项
    n1 = 1
    n2 = 1
    count = 2 # 判断输入的值是否合法
    if num_n <= 0:
    print("请输入一个正整数。")
    elif num_n == 1:
    print("斐波那契数列:")
    print(n1)
    else:
    print("斐波那契数列:")
    print(n1,",",n2,end=" , ")
    while count < num_n:
    nth = n1 + n2
    print(nth,end=" , ")
    # 更新值
    n1 = n2
    n2 = nth
    count += 1
  • 上述代码运行结果如下:

    请输入你需要几项:4  #键入4,求斐波那契数列前四项
    斐波那契数列:
    1 , 1 , 2 , 3 , # 得到斐波那契数列前四项

从上面两中方法的对比可以看出,递归函数的作用和循环的方法效果一样,即递归函数本质上是一个方法的循环调用,注意:有可能会出现死循环。因此,使用递归函数时,一定要定义递归的边界(即什么时候退出循环)。

以上两个案例是递归函数的经典案例,需要记住其使用方法。循环能干的事,递归都能干;递归能干的循环不一定能干

递归函数特点

递归:自我调用且有完成状态。

  1. 每一级函数调用时都有自己的变量,但是函数代码并不会得到复制,如计算5的阶乘时每递推一次变量都不同;

  2. 每次调用都会有一次返回,如计算5的阶乘时每递推一次都返回进行下一次;

  3. 递归函数中,位于递归调用前的语句和各级被调用函数具有相同的执行顺序;

  4. 递归函数中,位于递归调用后的语句的执行顺序和各个被调用函数的顺序相反;

  5. 递归函数中必须有终止语句。

递归函数的缺点: 过深的调用会导致栈溢出

递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

  • 使用python写的递归程序如果递归太深, 那么极有可能因为超过系统默认的递归深度限制而出现

    • 例如使用递归计算阶乘时,传入参数值1000来调用函数factoria(1000),运行会报错:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in factoria
...
File "<stdin>", line 4, in factoria
RuntimeError: maximum recursion depth exceeded
  • 解决上述报错问题的方法很简单, 人为将系统设定的递归深度设置为一个较大的值即可:

    import sys
    sys.setrecursionlimit(1000000) #括号中的值为递归深度

参考资源:

『Python基础-15』递归函数 Recursion Function的更多相关文章

  1. 『Python基础-12』各种推导式(列表推导式、字典推导式、集合推导式)

    # 『Python基础-12』各种推导式(列表推导式.字典推导式.集合推导式) 推导式comprehensions(又称解析式),是Python的一种独有特性.推导式是可以从一个数据序列构建另一个新的 ...

  2. 『Python基础-7』for循环 & while循环

    『Python基础-7』for循环 & while循环 目录: 循环语句 for循环 while循环 循环的控制语句: break,continue,pass for...else 和 whi ...

  3. 『Python基础-4』字符串

    # 『Python基础-4』字符串 目录 1.什么是字符串 2.修改字符串 2.1 修改字符串大小 2.2 合并(拼接)字符串 2.3 使用乘号'*'来实现字符串的叠加效果. 2.4 在字符串中添加空 ...

  4. 『Python基础-11』集合 (set)

    # 『Python基础-11』集合 (set) 目录: 集合的基本知识 集合的创建 访问集合里的值 向集合set增加元素 移除集合中的元素 集合set的运算 1. 集合的基本知识 集合(set)是一个 ...

  5. 『Python基础-10』字典

    # 『Python基础-10』字典 目录: 1.字典基本概念 2.字典键(key)的特性 3.字典的创建 4-7.字典的增删改查 8.遍历字典 1. 字典的基本概念 字典一种key - value 的 ...

  6. 『Python基础-9』元祖 (tuple)

    『Python基础-9』元祖 (tuple) 目录: 元祖的基本概念 创建元祖 将列表转化为元组 查询元组 更新元组 删除元组 1. 元祖的基本概念 元祖可以理解为,不可变的列表 元祖使用小括号括起所 ...

  7. 『Python基础-8』列表

    『Python基础-8』列表 1. 列表的基本概念 列表让你能够在一个地方存储成组的信息,其中可以只包含几个 元素,也可以包含数百万个元素. 列表由一系列按特定顺序排列的元素组成.你可以创建包含字母表 ...

  8. 『Python基础-6』if语句, if-else语句

    # 『Python基础-6』if语句, if-else语句 目录: 条件测试 if语句 if-else语句 1. 条件测试 每条if语句的核心都是一个值为True或False的表达式,这种表达式被称为 ...

  9. 『Python基础-5』数字,运算,转换

    『Python基础-5』数字,运算,转换 目录 基本的数字类型 二进制,八进制,十六进制 数字类型间的转换 数字运算 1. 数字类型 Python 数字数据类型用于存储数学上的值,比如整数.浮点数.复 ...

随机推荐

  1. javascript实现的动态添加表单元素input,button等(appendChild)

    写一个小系统时,需要动态添加表单元素,按自己的实现方法写了这篇教程! 我想各位在很多网站上都看到过类似的效果! 1.先用document.createElement方法创建一个input元素! 代码如 ...

  2. nginx转发配置

    nginx upstream backend19050 { server 10.10.10.10:19050 max_fails=3 fail_timeout=30s; } server { list ...

  3. 什么是封装? ----------------php中"public"类似的访问修饰符分别有什么作用?----什么是抽象?抽象的关键字以及用法----- 什么是接口?接口的关键字以及用法-------------

    什么是封装? ------------------------------------封装是php面向对象的其中一个特性,将多个可重复使用的函数封装到一个类里面.在使用时直接实例化该类的某一个方法,获 ...

  4. MARKS:路由器桥接

    仅供参考…… 测试使用环境:Tplink & Tenda渣渣路由器.其他环境或不同. 设置注意事项:副路由器网段设置和主路由一致.主路由不需要开启WDS.副路由器开启WDS(连接ok,状态即显 ...

  5. POJ-1061 青蛙的约会---扩展欧几里得算法

    题目链接: https://cn.vjudge.net/problem/POJ-1061 题目大意: 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线 ...

  6. Linux.开关机&登出&用户管理

    关机重启: shutdown:         shutdown –h now 立该进行关机         shudown -h 1 "hello, 1 分钟后会关机了"    ...

  7. JDBC(5)ResSetMetaData&DatabaseMetaData&获取数据库主键的值

    ResSetMetaData 可用于获取关于 ResultSet 对象中列的类型和属性信息的对象: getColumnName(int column):获取指定列的名称 getColumnCount( ...

  8. 用python实现ping

    #!/usr/bin/env python #coding=utf-8 import os import argparse import socket import struct import sel ...

  9. Apple的UIAutomation环境搭建和入门知识

    简述 Xcode的instruments中的Automation是为了实现自动化测试的一个工具.实现方式有两种:它提供了两种实现方式, 1)     是通过JS脚本语言来执行自动化测试(普通自动化测试 ...

  10. mysql的入门基本使用(适合新手学习)

    登陆Mysql数据库mysql -u root -p 展示(查询)所有数据库show databases;进入数据库use dataname;创建数据库create database dataname ...