第二十一章 函数递归

news/2024/4/27 12:53:17/文章来源:https://www.cnblogs.com/jhno1/p/16778340.html

一、函数递归调用介绍

函数不仅可以嵌套定义,还可以嵌套调用,即在调用一个函数的过程中,函数内部又调用另一个函数,而函数的递归调用指的是在调用一个函数的过程中又直接或间接地调用该函数本身。例如在调用f1的过程中,又调用f1,这就是直接调用函数f1本身
def f1():print('from f1')f1()
f1()# 在调用f1的过程中,又调用f2,而在调用f2的过程中又调用f1,这就是间接调用函数f1本身

image

def f1():print('from f1')f2()def f2():print('from f2')f1()f1()

image

从上图可以看出,两种情况下的递归调用都是一个无限循环的过程,但在python对函数的递归调用的深度做了限制,因而并不会像大家所想的那样进入无限循环,会抛出异常,要避免出现这种情况,就必须让递归调用在满足某个特定条件下终止。ps:
#1. 可以使用sys.getrecursionlimit()去查看递归深度,默认值为1000,虽然可以使用
import sys
sys.getrecursionlimit()查看递归深度,默认值为1000
sys.setrecursionlimit()去设定该值,但仍受限于主机操作系统栈大小的限制#2. python不是一门函数式编程语言,无法对递归进行尾递归优化。

二、回溯与递推

下面我们用一个浅显的例子,阐释递归的原理和使用:某公司四个员工坐在一起,问第四个人薪水,他说比第三个人多1000,问第三个人薪水,第他说比第二个人多1000,问第二个人薪水,他说比第一个人多1000,最后第一人说自己每月5000,请问第四个人的薪水是多少?思路解析:
要知道第四个人的月薪,就必须知道第三个人的,第三个人的又取决于第二个人的,第二个人的又取决于第一个人的,而且每一个员工都比前一个多一千,数学表达式即:
salary(4)=salary(3)+1000 
salary(3)=salary(2)+1000 
salary(2)=salary(1)+1000 
salary(1)=5000
总结为: 
salary(n)=salary(n-1)+1000 (n>1) 
salary(1)=5000 (n=1) 
很明显这是一个递归的过程,可以将该过程分为两个阶段:回溯和递推。在回溯阶段,要求第n个员工的薪水,需要回溯得到(n-1)个员工的薪水,以此类推,直到得到第一个员工的薪水,此时,salary(1)已知,因而不必再向前回溯了。然后进入递推阶段:从第一个员工的薪水可以推算出第二个员工的薪水(6000),从第二个员工的薪水可以推算出第三个员工的薪水(7000),以此类推,一直推算出第第四个员工的薪水(8000)为止,递归结束。需要注意的一点是,递归一定要有一个结束条件,这里n=1就是结束条件。

image

# 代码实现:
def salary(n):if n==1:return 5000return salary(n-1)+1000s=salary(4)
print(s)# 执行结果:
8000
# 程序分析:
在未满足n\=\=1的条件时,一直进行递归调用,即一直回溯,见图左半部分。而在满足n\=\=1的条件时,终止递归调用,即结束回溯,从而进入递推阶段,依次推导直到得到最终的结果。递归本质就是在做重复的事情,所以理论上递归可以解决的问题循环也都可以解决,只不过在某些情况下,使用递归会更容易实现,比如有一个嵌套多层的列表,要求打印出所有的元素,代码实现如下
items=[[1,2],3,[4,[5,[6,7]]]]
def foo(items):for i in items:if isinstance(i,list): #满足未遍历完items以及if判断成立的条件时,一直进行递归调用foo(i) else:print(i,end=' ')foo(items) #打印结果1 2 3 4 5 6 7
使用递归,我们只需要分析出要重复执行的代码逻辑,然后提取进入下一次递归调用的条件或者说递归结束的条件即可,代码实现起来简洁清晰

三、python中的递归效率低且没有尾递归优化

#python中的递归
python中的递归效率低,需要在进入下一次递归时保留当前的状态,在其他语言中可以有解决方法:尾递归优化,即在函数的最后一步(而非最后一行)调用自己。
但是python又没有尾递归,且对递归层级做了限制#总结递归的使用:
1. 必须有一个明确的结束条件2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

四、二分法

想从一个按照从小到大排列的数字列表中找到指定的数字,遍历的效率太低,用二分法(算法的一种,算法是解决问题的方法)可以极大低缩小问题规模

l=[1,2,10,30,33,99,101,200,301,311,402,403,500,900,1000] #从小到大排列的数字列表def search(n,l):print(l)if len(l) == 0:print('not exists')returnmid_index=len(l) // 2if n > l[mid_index]:#in the rightl=l[mid_index+1:]search(n,l)elif n < l[mid_index]:#in the leftl=l[:mid_index]search(n,l)else:print('find it')search(3,l)
l=[1,2,10,30,33,99,101,200,301,402]def search(num,l,start=0,stop=len(l)-1):if start <= stop:mid=start+(stop-start)//2print('start:[%s] stop:[%s] mid:[%s] mid_val:[%s]' %(start,stop,mid,l[mid]))if num > l[mid]:start=mid+1elif num < l[mid]:stop=mid-1else:print('find it',mid)returnsearch(num,l,start,stop)else: #如果stop > start则意味着列表实际上已经全部切完,即切为空print('not exists')returnsearch(301,l)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_398893.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot(三)

视频链接&#xff1a;https://www.bilibili.com/video/BV1XQ4y1m7ex/?vd_source9545770e4a2968c05878ffac8589ec6c 视频选集&#xff1a;P58— P92 文章目录1.接口架构风格-RESTful1.1 认识REST1.2 RESTful的注解1.2.1 PathVariable1.2.2 PostMapping1.2.3 DeleteMapping1.2.4…

分布式缓存

本文介绍关于缓存的常用设计模式。以及如何保证缓存的一致性进行分类讨论。 还会介绍关于缓存失效的常见问题&#xff0c;以及针对缓存失效的解决方法。 在高并发的环境下&#xff0c;比如春节抢票大战&#xff0c;一到放票的时间节点&#xff0c;分分钟大量用户以及黄牛的各种…

魔改xxl-job,彻底告别手动配置任务!

xxl-job是一款非常优秀的任务调度中间件,轻量级、使用简单,但是苦于手动注册任务久矣,今天就来魔改一下,实现任务的自动注册!原创:微信公众号 码农参上,欢迎分享,转载请保留出处。哈喽大家好啊,我是Hydra。 xxl-job是一款非常优秀的任务调度中间件,轻量级、使用简单、…

12个小细节让普源示波器使用更加高效(上)

俗话说细节决定成败&#xff0c;示波器作为电子测量的第一工具&#xff0c;虽然使用简单&#xff0c;但并不是每个人都能注意到细节。运用好细节&#xff0c;可以使你的示波器使用更加的便捷。以下由安泰测试带来普源示波器测量相关的12个小细节可作为示波器常识快速自检的小文…

Spring Boot(4):@Import注解和@Conditional注解

说明&#xff1a;基于atguigu学习笔记。 在了解spring boot自动配置原理前&#xff0c;再来了解下两个注解Import注解和Conditional注解。 Import Import注解主要用于导入某些特殊的Bean&#xff0c;这些特殊的Bean和Bean Definitaion 有关。 主要用于导入Configuration 类…

Python实现桌面挂件,做一只可爱的桌面宠物~

文章目录嗨嗨&#xff0c;大家好 ~ 我是小圆相关文件开发工具相关模块&#xff1a;环境搭建安装原理简介1.初始化一个窗口组件&#xff1a;效果2.设置一下窗口的属性&#xff1a;随机导入一张图片&#xff0c;看效果随机导入一个宠物的所有图片的函数代码3.宠物随机出现在桌面上…

服务端渲染的探索与实践

服务端渲染(SSR)近两年炒得很火热,相信各位同学对这个名词多少有所耳闻。本节我们将围绕“是什么”(服务端渲染的运行机制)、“为什么”(服务端渲染解决了什么性能问题 )、“怎么做”(服务端渲染的应用实例与使用场景)这三个点,对服务端渲染进行探索。 服务端渲染是一…

GOM引擎登录器的研究,逆向技术在这款GOM20151108引擎上是一个大舞台

最近遇到一个逆向类课题&#xff0c;是关于GOM20151108版本对应登录器研究。刚接触传奇的时候是2002年&#xff0c;那时候网吧玩SF&#xff0c;都是手动用IP直接连接&#xff0c;当时的一款 联创传奇 很好玩&#xff0c;有传送戒子&#xff0c;木域戒指&#xff0c;土域戒指&am…

不会 Vue,但不影响我学 diff 算法

前言 现在社会各行各业大都面临着寒冬&#xff0c;互联网行业最近还出现了裁员潮&#xff0c;导致前端是越来越卷&#xff0c;普通学校的应届生不仅要跟985、211毕业的学生以及研究生进行竞争&#xff0c;甚至还需要和最近刚被裁的、有了几年工作经验的程序员竞争&#xff0c;…

page.json

uni-app需要给page.json文件需要进行配置路由,否则会不报错,也跳转不过去

【数模/启发式算法】蚁群算法

文章目录简介符号说明核心思想流程图文章使用到的测试函数基本步骤蚁群算法代码简介 蚁群算法是一种用来寻找优化路径的概率型算法。它由Marco Dorigo于1992年在他的博士论文中提出&#xff0c;其灵感来源于蚂蚁在寻找食物过程中发现路径的行为。 这种算法具有分布计算、信息正…

Arduino播放声音

玩软件有点虚无&#xff0c;没有实际东西&#xff0c;所以接下来要体验下硬件与软件结合。 1 Arduino Arduino是一种包含硬件&#xff08;各种型号的Arduino板&#xff09;和软件&#xff08;Arduino IDE&#xff09;的开源电子平台。硬件部分是可以用来做电路连接的Arduino电…

小白学习Java第四十三天

Git概述 &#xff08;一&#xff09;什么是Git Git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。版本控制是指对软件开发过程中各种程序代码、配置文件及说明文档等文件变更的管理&#xff0c;是软件配置管理的核心思想之一…

设计模式学习笔记(五) - 观察者模式 Observer

目录 观察者模式 Observer 一、背景描述 Version 1 (面向过程) Version 2 (面向对象) Version 3 (单个观察者) Version 4 (多个观察者) Version 5 (分离观察者与被观察者) 二、不同事件下的观察者模式 三、事件本身也可以形成继承体系 四、观察者常用场景 观察者模式…

Selenium基础 — 鼠标操作

1、鼠标事件介绍 前面例子中我们已经学习到可以用click()来模拟鼠标的单击操作&#xff0c;而我们在实际的web产品测试中发现&#xff0c;有关鼠标的操作&#xff0c;不单单只有单击&#xff0c;有时候还要用到右击&#xff0c;双击&#xff0c;拖动等操作&#xff0c;这些操作…

【Nginx】认识与基本使用 Nginx 实现反向代理、配置负载均衡

文章目录1. Nginx 概述1.1 Nginx 介绍1.2 Nginx 下载和安装1.3 Nginx 目录结构2. Nginx 命令3. Nginx 配置文件结构4. Nginx 具体应用4.1 部署静态资源4.2 反向代理4.2.1 介绍4.2.2 配置反向代理4.3 负载均衡4.3.1 介绍4.3.2 配置负载均衡4.3.3 负载均衡策略1. Nginx 概述 1.1…

Ubuntu开机界面出现“error found when loading /root/.profile”

原因 今天一开始按照一篇文章&#xff0c;想把普通用户的权限提高到最高权限&#xff0c;修改了**/etc/passwd**文件&#xff0c;然后重启&#xff0c;发现之前的用户进不去了&#xff0c;一开机就出现如下信息 解决方法 1、重启虚拟机进入recovery模式&#xff08;长按shi…

计算机网络-第一章 | 王道考研

目录 一、基本介绍 定义 功能 组成 分类 标准化工作 标准的分类 标准化工作相关组织 二、性能指标 ※ 速率 带宽 ※吞吐量 时延 时延带宽积 往返时延RTT 利用率 三、分层结构 ※ 分层基本规则 正式认识分层 7层OSI参考模型 怎么来的 怎么分的 怎么传的…

<特殊类设计与单例模式>——《C++高阶》

目录 1.请设计一个类&#xff0c;不能被拷贝 2. 请设计一个类&#xff0c;只能在堆上创建对象 3. 请设计一个类&#xff0c;只能在栈上创建对象 4. 请设计一个类&#xff0c;不能被继承 5. 请设计一个类&#xff0c;只能创建一个对象(单例模式) 后记&#xff1a;●由于…

GD32F307VC+WIN10+VSCODE+GCC+JLINK环境build

为了构建Cortex M系列单片机免费开源的开发环境&#xff0c;网络上了解来看VSCODEGCCJLINK是一套比较高效的组合方式&#xff0c;下面记录环境搭建的流程。 我这边的PC环境为 WIN10专业版64bit。 工具准备 1. arm-none-eabi-gcc下载及安装 官网下载链接&#xff1a;Downloa…