python_Day2_递归函数、迭代

2019.5.21     肥仔昨晚打碎了酱油玻璃瓶,好生气,还要起来清洁,早上有点困啊。。。抓紧时间学习了。

 

今天学习内容:递归函数(尾递归)、迭代

################################################################################

 

递归函数:

   如:阶乘:fac(n)=n * fac(n-1)       即n!=n*(n-1)*(n-2)*……*2*1
  
  递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。假设n=1000,就会溢出。

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

   报错:RuntimeError: maximum recursion depth exceeded in comparison

 
  解决方法:尾递归
    尾递归是指,在函数返回的时候,调用自身本身,并且return语句不能包含表达式(如上面就返回了乘法表达式)。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。
 

  综上,尾递归能解决递归过深调用的问题,本质上尾递归也是循环。多建了一个函数,使之是函数在循环进入后又退出,避免栈溢出

 
#######################################################################################
 
作业:汉诺塔(Hanoi Tower)(请编写move(n, a, b, c)函数,它接收参数n,表示3个柱子A、B、C中第1个柱子A的盘子数量,然后打印出把所有盘子从A借助B移动到C的方法,)
  
  这个真是个好问题,想了足足一天,不容易啊,递归思想

 

答案:

首先给函数名中的abc下一个定义:a=操作区;b=缓冲区;c=目标区 这样程序可以改为 : move(n,操作区,缓冲区,目标区)

我们的目的:将 操作区 的数移动到 目标区 里,所以函数执行只有一句话:操作区--->目标区

第一步:将 操作区a 前n-1个数移动到 缓冲区b 里,这时 缓冲区b 就是我们这一步的目标区;所以是move(n-1,a,c,b) 

第二步:将 操作区a 的最后一个数移动到 目标区c 里,即move(1, a, b, c)

注意: 这时,操作区a的东西已经全部移动到缓冲区b目标区c里了,操作区a已经为空了。 所以现在,缓冲区b就成为了新的操作区(里头有m=n-1个数),而之前的操作区a成为了新的缓冲区

所以第三步是将a、b交换后再一次执行move函数,即 move(m,b,a,c),并且此时m=n-1。

 

#################################################################################

迭代(lteration):

  1)通过for循环来遍历各种对象。例如对dict的迭代,默认是对key,如果要迭代value,for value in xx.values()  如果同时迭代key和value,可以用for k,v in xx.items()

 

  2)如何判断一个对象是否可迭代?

    通过collections模块的lterable类型判断:

  

 

 

  3)如果要对list 实现类似c那样的下标循环(用索引而不是元素来迭代)怎么办?

    enumerate 函数可以把一个list 变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身:

  

 

作业:请使用迭代查找一个list中最小和最大值,并返回一个tuple: 

 

 

 

 

 

posted @ 2019-05-21 22:12  Marvin_Tang  阅读(149)  评论(0编辑  收藏  举报