递归与迭代

1. 递归

1.1

1.2 递归形式

1.2.1 无返回值

  • 样式1
def st(n):
    if n <= 0:
        return
    #print (n)
    st(n-1)
    print (n)


print (st(5))

#----------
1
2
3
4
5
None

- 样式2

def st(n):
    if n <= 0:
        return
    print (n)
    st(n-1)
    #print (n)


print (st(5))

#-------
5
4
3
2
1
None
  • 样式3
def st(n):
    if n <= 0:
        return
    print (n)
    st(n-1)
    print (n)

print (st(5))

# -----------

5
4
3
2
1
1
2
3
4
5
None

这里写图片描述
可以看出,递归的过程是调用st(n-1) 方法,在这个方法之前的处理都是在向右的方向中,也就是在向更深层调用的过程
在这个方法之后的处理都是在向左的方向中,也就是从更深层次向上返回的过程

假如一个递归函数上

def di(n)
    before_logic
    di(n-1)
    after_logic

而且整个过程一定是:

  1. 逐步向更深层次调用,并同时处理返回前的代码逻辑,即是before_logic
  2. 执行到结束条件,也就是递归出口处,并得到最深层处理的结果
  3. 逐步向上层返回,并同时处理返回时的代码逻辑,即是after_logic

1.2.2 有返回值

  • 阶乘

简单来说,有返回值和无返回值在过程上没有区别,区别只是在第三步中,有返回值的话会有一个return ,把下一层的结果返回给上一层

也就是说,有返回值的第三步after_logicreturn di(n-1) ,而无返回值的第三步却不是return

  • 形式1
def fa(n):
    if n == 1:
        return 1
    return fa(n-1) * n

print (fa(4))

结果是

120
  • 形式2

打印每一步结果如下:

def fa(n):
    if n == 1:
        print (1," : ",1)
        return 1
    m = fa(n-1) * n
    print (n," : ",m)
    return m

print (fa(4))

结果是:

1  :  1
2  :  2
3  :  6
4  :  24
5  :  120
120

所以递归中:下面两句等价

    return fa(n-1) * n

## --或者--

    m = fa(n-1) * n
    return m

这里写图片描述

结合形式2与上图的调用关系可以看出,整个过程是先到达最深的那一层,然后才开始一层一层地向上return

这种情况是把最深一层的值一层一层地向上传递,在传递过程中的每一层,对接收到的值可以进行统一规则的处理(比如上例中是fa(n-1) * n

这就相当于第三步中,在返回结果中进行两步逻辑

  1. 将每一层的处理逻辑结果 * n
  2. return

1.2.3 多重递归

  • Fibonacci数列
  • 汉诺塔

汉诺塔

def fib(n):
    if n == 1 or n ==2:
        return 1
    return fib(n-1) + fib(n-2)

print (fib(5))

或者

def fib(n):
    if n == 1 or n ==2:
        return 1
    m = fib(n-1) + fib(n-2)
    return m

print (fib(5))

或者

def fib(n):
    if n == 1 or n ==2:
        return 1
    s = fib(n - 1)
    t = fib(n - 2)
    return s + t

print (fib(5))

过程如下:

这里写图片描述

可以看出,整个流程几乎是按照上图中的箭头方向从上往下走过来的

这和前面的递归形式其实本质上是一样的

def di(n)   
    di(n1)
    di(n2)  

这个递归过程其实是分开两步的

  • 第一步di(n1)

  • 第二步di(n2)

从整体大步骤上来讲,只有两步,先是di(n1),再是di(n2)
也就是di(n1) 全部执行完后,返回到main出发点后,再执行di(n2)

从小步骤上来讲,无论是di(n1) 还是di(n2) ,再向下一层执行的过程是相同的。(也就是图中的意思),都是从最深层回到上一层的出发点后,出现分支。

1.3 递归种类

即1.2中的各种样式

1.3.1 尾递归

  • 比如阶乘

递归调用语句只有一个,而且是处在算法的最后

1.3.2 单向递归

  • 比如Fibonacci数列

单向递归是指递归算法中虽然有多处递归调用语句,但各递归调用语句的参数之间没有关系,并且这些递归
调用语句都处在递归算法的最后。

2. 迭代

迭代:利用变量的原值推算出变量的一个新值.如果递归是自己调用自己的话,迭代就是A不停的调用B.

递归中一定有迭代,但是迭代中不一定有递归,大部分可以相互转换.能用迭代的不用递归,递归调用函数,浪费空间,并且递归太深容易造成堆栈的溢出.


# 这是递归
def funA(n):
    if n < 1:
        return 1
    return n + funA(n-1)

# 这是迭代
def funB(n):
    s = 0
    for i in range(1,n):
        s = s + i
    return s

3. 转化

参考
http://blog.csdn.net/agileclipse/article/details/8551228

猜你喜欢

转载自blog.csdn.net/zengchen73/article/details/76400758
今日推荐