python数据结构学习笔记-2016-11-11-01-递归

        递归(recursion):通过将大问题分解成几个相对简单的且解法相同或类似的子问题,来将问题解决的方式。

        10.1 递归函数

         一个可以调用自身的函数称为递归函数(recursive function)。

         递归调用(recursive calls)

         递归展开(recursive unwinding)

        10.2 递归的性质

         递归需满足如下条件:

  • 递归解决方法必须要有一个终止条件(base case);
  • 递归解决方法必须要有一个递归条件(recursive case);
  • 递归解决方法必须逐步向终止条件接近。
         10.2.1 阶乘

#-*-coding: utf-8-*-

# 阶乘

def fact(n):
    assert n >= 0, "Factorial not defined for negative values."
    if n < 2:
        return 1
    else:
        return n * fact(n-1)
          10.2.2 递归调用树

          常用递归树(recursive call tree)来表示一个递归函数的调用过程。


          10.2.3 Fibonacci序列

#-*-coding: utf-8-*-

# Fibonacci序列

def fib(n):
    assert n >= 0, "Fibonacci not defined for n < 0."
    if n == 1 or n == 0:
        return 1
    else:
        return fib(n-1) + fib(n-2)


         10.3 递归的原理
         10.3.1 运行时栈(run time stack)
          活动记录(activation record):每一次调用一个函数之后,会自动生成,以保存该函数的相关信息。
          返回地址(return address):这些信息中就包括了返回地址。它是当函数执行完成时,下一条将要被执行指令的位置。
          每次调用一个函数,都会产生一条活动记录,这些活动记录会自动被储存在运行时栈(run time stack)中,当函数执行完成时,这些活动记录被自动弹出,并销毁。
          当递归函数函数时,运行时栈中的活动记录就可用于回溯或返回到递归函数完成执行后的下一条指令的位置。
          以阶乘函数为例:
>>> def main():
...     y = fact(2)
>>> main()
           当main()函数执行时,第一条活动记录产生并被压入运行时栈中,之后是递归函数fact(),一直到n=0这一终止条件,这些活动记录开始逐个从运行时栈中弹出。


         10.3.2 使用栈
          考虑反向打印出单链表中的元素。
          蛮力法,其时间复杂度是O(n²)。
#-*-coding: utf-8-*-

# 使用蛮力法反向打印单链表中的元素

def printListBF(head):
    # 先计数
    numNodes = 0
    curNode = head
    while curNode is not None:
        curNode = curNode.next
        numNodes += 1
    # 再遍历,第一次遍历,打印出最后一个元素,第二次遍历,打印出倒数第二个元素,依次类推
    for i in range(numNodes):
        curNode = head
        for j in range(numNodes - i):
            curNode = curNode.next
        print curNode.data
          使用栈,其时间复杂度是O(n)。
#-*-coding: utf-8-*-

# 使用栈来反向打印单链表中的元素,非递归

from lliststack import Stack

def printListStack(head):
    s = Stack()
    # 先遍历一次链表,将元素依次压入栈中
    curNode = head
    while curNode is not None:
        s.push(curNode.data)
        curNode = curNode.next
    # 再将栈中元素弹出,并打印
    while not s.isEmpty():
        item = s.pop()
        print item
          使用递归,这是基于一个链表可以看成是连接与上一个结点的结点。

#-*-coding: utf-8-*-

# 使用递归反向打印单链表中的元素

def printList(node):
    if node is not None:
        printList(node.next)
        print node.data
        其运行时栈如下:


          递归的情况与使用栈的情况,基本没什么差别,只是递归解法中循环和栈是隐式的。

          10.3.3 尾递归
           如果一个函数的递归形式的调用都初现在函数的末尾,则称为尾递归(tail recursion)。
           将之前的代码改为:
#-*-coding: utf-8-*-

# 尾递归

def printInorder(node):
    if node is not None:
        print node.data
        printInorder(node.next)
           在先前,我们是先将元素压入栈中,再执行print。在这里,就不需要将元素全部压入栈中,再执行print,此时可以使用迭代来代替递归。






          

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值