递归

1.什么是递归:

其实前面都提过,但没有详细讲。多次调用自身就叫递归

看图,这种就叫递归

看过盗梦空间没?其实也是递归

2.递归需要满足条件:

  • 有调用函数自身
  • 有一个正确的返回条件来结束
  • 在使用递归策略时,必须有一个明确的递归结束条件,即递归出口

3.递归和迭代的区别:

  • 递归:(recursion)指的是一个函数不断调用自身的行为,比如以编程方式输出著名的斐波纳契数列
  • 遍历:(traversal)指的是按照一定的规则访问树形结构的每一个节点,而且每个节点都只访问一次

4.递归的深度在python3版本上默认设置100层,作为保护设置

因为如果一直无限递归的结果就和无线循环一样,直到计算机崩溃才结束

修改递归深度(前面在sys模块提到过):

>>> import sys
>>> sys.setrecursionlimit (100000)  #括号内的参数即为递归深度

5.递归实际运用:

例1:求一个数的阶乘

1)使用while:

# -×- coding:utf-8 -*-a=int(input("请输入一个正整数:"))
s=1
while a-1!=-1:
    s=s*a
    a=a-1
    if  a<0:
        break
print(s)

结果:

>>> 请输入一个正整数:7
5040

2)使用函数:


# -×- coding:utf-8 -*-
def M(a):
    s=a
    for i in range(1,a):
        s*=i    return s
a=int(input("请输入一个正整数:"))
s=M(a)
print("数字 %d 的阶乘为:%d"%(a,s))

结果:

请输入一个正整数:8

数字 8 的阶乘为:40320

3)当然也可以函数+while方法:

# -×- coding:utf-8 -*-def M(a):
    s=1
    while a-1!=-1:
        s=s*a
        a=a-1
    return s
a=int(input("请输入一个正整数:"))
s=M(a)
print("数字 %d 的阶乘为:%d"%(a,s))

效果是一样的,就不再输出了

5)使用for循环:

# -×- coding:utf-8 -*-def f(n):
    result=n
    for i  in range(1,n):
        result*=i
    return result

结果:

>>> temp=f(8)
>>> temp
40320

6)使用递归:


# -×- coding:utf-8 -*-
def M(a):
    if a==1:
        return 1
    else:
        return a*M(a-1)

结果:

>>> temp=M(8)
>>> temp
40320

使用了这么多方法,你有没有感觉,其实使用递归,思路上是最简单的,当然不去考虑代码量的问题。递归的优势就是分治思想,分治思想就是把一个大问题分成很多个相同解决方法的小问题,当把解决的一个小问题利用程序重复进行多次直到把这个大问题解决掉。

例2:利用斐波纳契数列打印在给定周期内生出的兔崽子数

1)使用迭代:

# -×- coding:utf-8 -*-def tuzi(n):
    n1=1
    n2=1
    n3=1   #此为初始值
    if n<1:
        print("输入有误!")
        return "Error"
    while (n-2)>0:
        n3=n2+n1
        n1=n2
        n2=n3
        n-=1
    return n3
n=int(input("请输入周期数:"))
result=tuzi(n)
if result!="Error":
    print("总共有%d只兔子"%result)

结果:

>>> result=tuzi(8)
>>> result
21

2)使用函数,列表结合实现:

3)使用递归:

def tuzi(n):
    if n<1:
        print("输入有误:")
        return "Error"
    if n==1 or n==2:
        return 1
    else:
        return tuzi(n-1)+tuzi(n-2)
n=int(input("请输入经过的月份数:"))
result=tuzi(n)
if result!="Error":
    print("总共有%d只兔崽子"%result)
print("结束!")

结果:

>>> result=tuzi(8)
>>> result
21

看完这么多,我想你应该对递归有所了解了,是的,迭代比递归快很多,迭代因为只是遍历对象内的所有参数,而递归是每次都会调用自身,每次都会处理一次属于自己的那一段代码块,所以递归更慢,但是思路确实很清晰,并且使用递归函数时需要注意防止栈溢出

好的,最后一例,如果你会了,那么递归你就已经掌握了:

例3:使用递归求解汉诺塔

了解:什么是汉诺塔?

法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石柱(或者石针)。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片圆盘,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些圆盘:一次只移动一个圆盘,不管在哪根针上,小圆盘必须在大圆盘上面。僧侣们预言,当所有的圆盘都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽

比如三个罗盘三根柱子时:

我要把x柱上的圆盘转移到Z柱上,但是每次只能移动一个圆盘,思路是: 把小圆盘和中圆盘从X放到Y上,再把大圆盘放到Z上,再把小圆盘和中圆盘放到Z上就行对吧?

但实践起来就不止简简单单的一两句话的:

步骤:

1.把小圆盘和中圆盘借用Z移到Y上

  • 1):把小圆盘放到Z上
  • 2):把中圆盘放到Y上
  • 3):把小圆盘放到Y上

2.把大圆盘移到X上

通过这大的两步就把三个圆盘从x移到z上了。而第一步时又可以分为一个同类型的小问题,把其当作是两个圆盘时移动操作,而一个圆盘时就直接就移动过去。这就是递归最好的体现。但其实三个圆盘是很简单的,如果不止三个圆盘呢?如果就如上面所说有64个圆盘呢?所以这就需要程序解决了

参考答案:(在看答案前,我希望你已经努力做过)

# -*- coding:utf-8 -*-
def hanoi(n,x='x',y='y',z='z'):
    if n==1:
        print(x, "-->" ,z)
    else:
        hanoi(n-1,x,z,y) #将前n-1个盘子从x移动到y上
        print(x, "-->" ,z)#将最底下的最后个盘子从x移动到z上
        hanoi(n-1,y,x,z) #将y上的n-1个盘子移动到z上
n=int(input("请输入汉诺塔的层数:"))
hanoi(n)

hanoi

>>> hanoi(5,'x','y','z')
x --> z
x --> y
z --> y
x --> z
y --> x
y --> z
x --> z
x --> y
z --> y
z --> x
y --> x
z --> y
x --> z
x --> y
z --> y
x --> z
y --> x
y --> z
x --> z
y --> x
z --> y
z --> x
y --> x
y --> z
x --> z
x --> y
z --> y
x --> z
y --> x
y --> z
x --> z

结果

其实这个汉诺塔很简单,方法也很多,自己下去测试就懂了

这就是递归,在编程语言里很重要的一个概念

洗礼灵魂,修炼python(26)--编程核心之“递归”的更多相关文章

  1. Python面向对象编程核心思想

    原文地址https://blog.csdn.net/weixin_42134789/article/details/80194788 https://blog.csdn.net/happyjxt/ar ...

  2. 洗礼灵魂,修炼python(69)--爬虫篇—番外篇之feedparser模块

    feedparser模块 1.简介 feedparser是一个Python的Feed解析库,可以处理RSS ,CDF,Atom .使用它我们可从任何 RSS 或 Atom 订阅源得到标题.链接和文章的 ...

  3. 洗礼灵魂,修炼python(85)-- 知识拾遗篇 —— 深度剖析让人幽怨的编码

    编码 这篇博文的主题是,编码问题,老生常谈的问题了对吧?从我这一套的文章来看,前面已经提到好多次编码问题了,的确这个确实很重要,这可是难道了很多能人异士的,当你以为你学懂了,在研究爬虫时你发现你错了, ...

  4. 洗礼灵魂,修炼python(7)--元组,集合,不可变集合

    前面已经把列表的基本用法讲解完 接着讲python的几大核心之--元组(tuple) 1.什么是元组? 类似列表,但为不可变对象,之前提到列表是可变对象,所谓可变对象就是支持原处修改,并且在修改前后对 ...

  5. Python编程核心之makeTextFile.py和readTextFile.py

    引言: 最近大半年都在学习python编程,在双十一的时候购买了<Python编程核心>,看到makeTextFile.py和readTextFile.py两个例子有点错误,所以在这里给修 ...

  6. Python 编程核心知识体系(REF)

    Python 编程核心知识体系: https://woaielf.github.io/2017/06/13/python3-all/ https://woaielf.github.io/page2/

  7. Python 网络编程(二)

    Python 网络编程 上一篇博客介绍了socket的基本概念以及实现了简单的TCP和UDP的客户端.服务器程序,本篇博客主要对socket编程进行更深入的讲解 一.简化版ssh实现 这是一个极其简单 ...

  8. python高级编程:有用的设计模式1

    # -*- coding: utf-8 -*-__author__ = 'Administrator'#python高级编程:有用的设计模式#设计械是可复用的,某种程序上它对软件设计中觉问题提供的语言 ...

  9. python网络编程-01

    python网络编程 1.socket模块介绍 ①在网络编程中的一个基本组件就是套接字(socket),socket是两个程序之间的“信息通道”. ②套接字包括两个部分:服务器套接字.客户机套接字 ③ ...

随机推荐

  1. c/c++连接mysql数据库

    环境:win7 x64.vs2008.mysql 对于已经安装mysql的,查看mysql安装目录,如果安装目录下没有include和lib目录, 说明没有完全安装,需要下载mysql-connect ...

  2. 如何解决CDR x8安装时显示“已停止工作”

    相信很多朋友在安装cdr X8时会遇到这样一种情况,能装上去,但不能运行,弹出提示说CorelDRAW X8(64-bit)已停止工作.同样的X8安装包,在不同的电脑上测试有的没有问题,有的则会出现以 ...

  3. Java 中UDP原理机制及实现方式介绍(建议阅读者阅读前了解下Java的基础知识,一方便理解)

    1.基本概念介绍: 首先得简单介绍下UDP. UDP( User Datagram Protocol )协议是用户数据报,在网络中它与TCP协议一样用于处理数据包.在OSI模型中,在第四层——传输层, ...

  4. 最好的Laravel中文文档

    分页 配置 基本用法 给分页链接添加自定义信息 配置 在其它的框架中,分页有时很痛苦. 但是Laravel让分页简单到不可思议. 默认Laravel包含了两个分页视图, 在app/config/vie ...

  5. JavaScript闭包(closure)入门: 拿&quot;开发部&quot;和&quot;技术牛&quot;举个例子

    虽然只是一小段菜鸟的学习笔记 , 不过还是希望看到的高手看到不足的时候帮忙指点~ 一:代码和执行过程 /** * http://blog.csdn.net/ruantao1989 * ==>Ju ...

  6. linux进程解析--进程的退出及销毁

    一进程的退出: 当一个进程运行完毕或者因为触发系统异常而退出时,最终会调用到内核中的函数do_exit(),在do_exit()函数中会清理一些进程使用的文件描述符,会释放掉进程用户态使用的相关的物理 ...

  7. 最佳新秀Java(22)——再次了解泛型

    仿制药Java SE 1.5新功能.通用自然是参数化类型.即操作数据类型被指定为一个参数.这样的参数类型可以在课堂上使用.创建的接口和方法,他们被称为通用类..泛型方法. Java语言引入泛型的优点是 ...

  8. Oracle中的多表查询(笛卡尔积原理)

    本次预计讲解的知识点 1. 多表查询的操作.限制.笛卡尔积的问题: 2. 统计函数及分组统计的操作: 3. 子查询的操作,并且结合限定查询.数据排序.多表查询.统计查询一起完成各个复杂查询的操作: 一 ...

  9. string类的简洁版实现

    说是原创,差不多算是转载了,我也是看了好多大牛的写法,大牛的建议,自己加一总结,形成代码: 实现一个简洁版的string类,我觉得,下面的也够了:另外需要参见另外的写法: http://blog.cs ...

  10. 妙用 scale 与 transfrom-origin,精准控制动画方向

    上次发完 不可思议的纯 CSS 导航栏下划线跟随效果 这篇文章之后,很多朋友找我讨论,感叹 CSS 的奇妙. 然后昨天,群里一位朋友问到了一个和这个效果比较类似的效果,问如何 将下面这个动画的下划线效 ...