递归函数

什么是递归

  了解什么是递归 : 在函数中调用自身函数
  最大递归深度默认是 997/998 —— 是 python 从内存角度出发做得限制
  能看懂递归
  能知道递归的应用场景
  初识递归 —— 二分法的例子
  算法 —— 二分查找算法
  三级菜单 —— 递归实现

我们先来看一个简单的递归函数

#可以执行下,看下与递归函数执行的结果有什么不同
while True:
print('从前有座山') #一个简单的递归函数
def story():
print('从前有座山')
story()
print(111) #执行不到这句话 story() #RecursionError: maximum recursion depth exceeded while calling a Python object
# 递归的错误,超过了递归的最大深度

测试递归函数的深度

#测试以下 python 中的递归深度  默认 997

#修改递归限制
import sys
sys.setrecursionlimit(100000) #不要改 n=0
def rec():
global n
print('从前有座山')
n +=1
print(n)
rec()
rec() # 如果递归次数太多,那么就不适合使用递归来解决问题
# 递归的缺点 : 占内存
# 递归的优点: 会让代码变简单

递归的逻辑

当你想解决一个问题时,需要知道另一个问题的答案
且下一个问题和前面的问题处理方法一致
递归是自上往下解决问题的

好比这样的问题

张三 多大       n = 1   age(1) = age(2)+2 = age(n+1) + 2
张三 比 李四 大两岁
李四 多大? n = 2 age(2) = age(3) + 2 = age(n+1) +2
李四 比 王五 大两岁
王五 多大 n = 3 age(3) = age(4) + 2 = age(n+1) +2
王五 比 赵六 大两岁
赵六 多大?
赵六 40 了 n = 4 age(4) = 40

我们把上面的逻辑写一个递归函数

def age(n):
if n == 4:
return 40
elif n >0 and n < 4:
return age(n+1) + 2
print(age(1)) #输出结果 46

这个 46 是怎么产生的呢?我们下面来看

def age(1):
if 1 == 4:
return 40
elif 1 > 0 and 1 < 4:
return 46 #于是最终得到 46 的结果 def age(2):
if 2 == 4:
return 40
elif 2 >0 and 2 < 4:
return age(3) + 2 # age(3) 的返回结果加 2 得到 44,返回给 age(1) def age(3):
if 3 == 4:
return 40
elif 3 >0 and 3 < 4:
return age(n+1) + 2 #4、age(4) + 2 得到 42 返回给age(2) def age(4):
if 4 == 4: #2、发现下面判断不在满足条件
return 40 #3、于是返回 return 40,注意:这里返回给了调用着 age(3)
elif n >0 and n < 4:
return age(n+1) + 2 #1、这里 age(3+1) 得到 age(4) ,再次调用

小结:

超过最大递归限制的报错
只要写递归函数,必须要有结束条件。

返回值
1、不要只看到return就认为已经返回了。要看返回操作是在递归到第几层的时候发生的,然后返回给了谁。
2、如果不是返回给最外层函数,调用者就接收不到。
3、需要再分析,看如何把结果返回回来。

二分查找算法

什么叫算法
计算的方法 : 人脑复杂 计算机简单

我们现在学习的算法 都是过去时
  了解基础的算法 才能创造出更好的算法
  不是所有的事情都能套用现成的方法解决的
  有些时候会用到学过的算法知识来解决新的问题

二分查找算法 必须处理有序的列表
k = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

基础版,列表的 k 的下标乱了

k = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
def find(lis,aim):
#获取中间值
mid = len(lis)//2
#如果中间值大于 aim
if lis[mid] > aim:
new_lis = lis[:mid]
find(new_lis,aim)
elif lis[mid] < aim:
new_lis = lis[mid + 1:]
find(new_lis,aim)
else:
print('找到了:'+ str(aim) + ' 所在位置为:'+ str(mid)) find(k,66)

升级版,解决了下标问题

k = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
def find(lis,aim,start = 0,end = len(k)):
#获取中间值
mid = (end - start)//2 + start
#如果中间值大于 aim
if lis[mid] > aim:
find(lis,aim,start = start,end = mid-1)
elif lis[mid] < aim:
find(lis,aim,start = mid + 1,end = end)
else:
print('找到了:'+ str(aim) + ' 所在位置为:',mid) find(k,18)
find(k,43)

继续升级
end 的问题
我们不希望每次找一个列表的都要修改函数中额 len(k) 这样函数就没有了可用性

k = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
def find(lis,aim,start = 0,end = None):
end = len(lis) if end is None else end
#获取中间值
mid = (end - start) // 2 + start
#中间值大于 aim
if lis[mid] > aim:
find(lis,aim,start = 0,end = mid - 1)
elif lis[mid]< aim:
find(lis,aim,start= mid + 1,end = end)
else:
print('找到了:'+str(aim)+"位于"+str(mid))
find(k,69)

接着升级
找不到所要查找的值怎么处理

k = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
def find(lis,aim,start = 0,end = None):
end = len(lis) if end is None else end
#获取中间值
mid = (end - start) // 2 + start
if start <= end:
#中间值大于 aim
if lis[mid] > aim:
find(lis,aim,start = 0,end = mid - 1)
elif lis[mid]< aim:
find(lis,aim,start= mid+1,end = end)
else:
print('找到了:'+str(aim)+"位于"+str(mid))
else:
print('找不到这个值')
find(k,68)

最后返回值的问题,因为我们希望最后的结果只是一个我们想要的值

k = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
def find(lis,aim,start = 0,end = None):
end = len(lis) if end is None else end
#获取中间值
mid = (end - start) // 2 + start
if start <= end:
#中间值大于 aim
if lis[mid] > aim:
return find(lis,aim,start = 0,end = mid - 1)
elif lis[mid]< aim:
return find(lis,aim,start= mid+1,end = end)
else:
# print('找到了:'+str(aim)+"位于"+str(mid))
return mid
else:
return'找不到这个值' print(find(k,5))

为了更加了解递归函数和上面的二分查找法可以拆开上面的函数分析下面的三种方法

# 67  发生两次调用
# 66 发生好几次
# 44 找不到

day 17 - 1 递归函数的更多相关文章

  1. day 17 - 2 递归函数练习

    1.斐波那契   问第n个斐波那契数是多少 #这个效率是低的,最好不要使用双递归 def fib(n): if n == 1 or n == 2: return 1 return fib(n-1) + ...

  2. C++扬帆远航——17(递归函数求阶乘)

    /* * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:阶乘.cpp * 作者:常轩 * 微信公众号:Worldhell ...

  3. js 递归函数的使用及常用函数

    1.递归函数的使用: 公园里有一堆桃子,猴子每天吃掉一半,挑出一个坏的扔掉,第6天的时候发现还剩1个桃子,问原来有多少个桃子 var peache;function peaches(n) { if ( ...

  4. Python基础之递归函数与二分法

    一.递归函数 定义: 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 我们来举个例子吧,比如:有个人问“egon”年龄,他说比“小大”大5岁,“小大”又说比“小保 ...

  5. day15 函数的使用方法:递归函数

    这里归纳的知识点主要就是: 浮点数,复数, int,整形:float,浮点数:complx,复数: # 实数: # 有理数 有限小数 1.2 # 无限循环小数 1.23232323232323.... ...

  6. day17:递归函数

    1,递归函数是一个函数体系,非常的难 2,练习题一 # 3.用map来处理字符串列表,把列表中所有人都变成sb,比方alex_sb name=['alex','wupeiqi','yuanhao',' ...

  7. python 全栈开发,Day15(递归函数,二分查找法)

    一.递归函数 江湖上流传这这样一句话叫做:人理解循环,神理解递归.所以你可别小看了递归函数,很多人被拦在大神的门槛外这么多年,就是因为没能领悟递归的真谛. 递归函数:在一个函数里执行再调用这个函数本身 ...

  8. python基础之lambda,sort,filter,map,递归函数的运用

    内容梗概:1. lamda 匿名函数2. sorted()3. filter()4. map()5. 递归函数 1.lambda 形式: lambda 参数:返回值 f = lambda x,y: x ...

  9. python 递归函数操作方法

    .递归 是指函数/过程/子程序在运行过程序中直接或间接调用自身而产生的重入现象.在计算机编程里,递归指的是一个过程:函数不断引用自身,直到引用的对象已知.使用递归解决问题,思路清晰,代码少.但是在主流 ...

随机推荐

  1. LVS负载均衡集群

    回顾-Nginx反向代理型负载 负载均衡(load balance)集群,提供了一种廉价.有效.透明的方法,来扩展网络设备和服务器的负载.带宽.增加吞吐量.加强网络数据处理能力.提高网络的灵活性和可用 ...

  2. grep -v、-e、-E

    在Linux的grep命令中如何使用OR,AND,NOT操作符呢? 其实,在grep命令中,有OR和NOT操作符的等价选项,但是并没有grep AND这种操作符.不过呢,可以使用patterns来模拟 ...

  3. Navicat Premium 12.0.18安装与激活

    因为要学习测试,postgresql , 没弄过所以用这个软件... https://www.jianshu.com/p/42a33b0dda9c

  4. 【模板】 $\text{K}$ 短路

    Tags 搜索.\(\text{A*}\).很酷很炫的算法 定义二元组\(\text{DIS(X,Now)}\)表示到达\(\text{X}\)点,路程是\(\text{Now}\): 反向\(\te ...

  5. 在Mac OS X下使用Apache、PHP、MySQL、Netbeans、Yii

    本文环境: Mac OS X:10.8.4 Apache:2.2.22 PHP:5.3.15 Netbeans:7.3.1 Yii:1.1.14 Mac OS X是内置了Apache服务器的,不过默认 ...

  6. 基于SpringBoot搭建应用开发框架(二) —— 登录认证

    零.前言 本文基于<基于SpringBoot搭建应用开发框架(一)——基础架构>,通过该文,熟悉了SpringBoot的用法,完成了应用框架底层的搭建. 在开始本文之前,底层这块已经有了很 ...

  7. 微信小程序:动画(Animation)

    简单总结一下微信动画的实现及执行步骤. 一.实现方式 官方文档是这样说的:①创建一个动画实例 animation.②调用实例的方法来描述动画.③最后通过动画实例的 export 方法导出动画数据传递给 ...

  8. building 'twisted.test.raiser' extension error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools

    Error msg: building 'twisted.test.raiser' extension error: Microsoft Visual C++ 14.0 is required. Ge ...

  9. 深入剖析Redis系列:Redis数据结构与全局命令概述

    前言 Redis 提供了 5 种数据结构.理解每种数据结构的特点,对于 Redis 的 开发运维 非常重要,同时掌握 Redis 的 单线程命令处理 机制,会使 数据结构 和 命令 的选择事半功倍. ...

  10. <Android基础> (五) 广播机制

    1)接收系统广播:a.动态注册监听网络变化 b.静态注册实现开机启动 2)发送自定义广播:a.发送标准广播 b.发送有序广播 3)使用本地广播 第五章 5.1 广播机制 Android中的每个程序都可 ...