欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

递归以及Python尾递归优化

程序员文章站 2024-03-16 15:12:58
...

递归

每个递归函数都有两部分:
1. 基线条件
一个或多个结束条件(if),不再调用函数自身,从而避免无限递归
2. 递归条件
调用函数自身func()

递归与循环抉择

使用循环,程序的性能可能更高;使用递归,程序可能更容易理解。
如何选择要看什么对你来说更重要。

汉罗塔(hanoi)问题

def hanoi(n, a, b, c):
    """
    n个盘子(最终移动到C):
        1. 把n-1个盘子从A通过C移动到B
        2. 把n个盘子从A移动到C
        3. 把n-1个盘子从B通过A移动到C
        汉罗塔移动次数的递推式:h(x) = 2h(x-1)+1
        h(64) = 18446744073709551615  --> 2^n
        假设婆罗门每秒移动一个盘子,则总共需要5800亿年!
    :param n:
    :param a:
    :param b:
    :param c:
    :return:
    """
    if n > 0:
        hanoi(n-1, a, c, b)
        print(f'Moving from {a} to {c}')
        hanoi(n-1, b, a, c)


hanoi(3, 'A', 'B', 'C')

尾递归

Python中的函数是通过栈结构实现的,
上一层(接近栈底)与下一层(接近栈顶)(自我的理解)之间只有调用关系,不涉及运算。

尾递归优化

Python中默认的递归深度为1000。
如果相互之间只有调用关系,就可以让上一层(接近栈底)出栈,可以避免调用栈溢出

代码示例

#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""递归

每个递归函数都有两部分:
1. 基线条件
   一个或多个结束条件(if),不再调用函数自身,从而避免无限递归
2. 递归条件
   调用函数自身func()

使用循环,程序的性能可能更高;使用递归,程序可能更容易理解。
如何选择要看什么对你来说更重要。

尾递归:
Python中的函数是通过栈结构实现的,
上一层(接近栈底)与下一层(接近栈顶)(自我的理解)之间只有调用关系,不涉及运算。

尾递归优化:
Python中默认的递归深度为1000.
如果相互之间只有调用关系,就可以让上一层(接近栈底)出栈,可以避免调用栈溢出
"""
import sys
from functools import wraps


class TailCallOptimizedError(Exception):

    def __init__(self, args, kwargs):
        self.args = args
        self.kwargs = kwargs


def tail_call_optimized(ori_func):
    @wraps(ori_func)
    def wrapper(*args, **kwargs):
        f = sys._getframe()
        if f.f_back and f.f_back.f_back and f.f_back.f_back.f_code == f.f_code:
            raise TailCallOptimizedError(args, kwargs)
        else:
            while 1:
                try:
                    return ori_func(*args, **kwargs)
                except TailCallOptimizedError as error:
                    args = error.args
                    kwargs = error.kwargs
    return wrapper


@tail_call_optimized
def factorial(n, acc=1):
    if n == 0:
        return acc
    return factorial(n - 1, n * acc)


print(factorial(10000))