Python递归函数深度解析:从原理到实战

Python递归函数深度解析:从原理到实战

递归是计算机科学中重要的编程范式,也是算法设计的核心思想之一。本文将通过20+实战案例,带你深入理解Python递归函数的精髓,掌握递归算法的实现技巧。

一、递归函数核心原理

1.1 递归三要素

  1. 基线条件:递归终止的条件
  2. 递归条件:问题分解的规则
  3. 状态传递:参数的状态变化

简单点说就是:自己调用自己,必须要有出口

1.2 执行过程解析

def countdown(n):
    if n <= 0:  # 基线条件
        print("Lift off!")
    else:       # 递归条件
        print(n)
        countdown(n-1)  # 状态传递

countdown(3)
"""
输出:
3
2
1
Lift off!
"""

二、基础递归模式

2.1 数值计算

阶乘计算
def factorial(n):
    return 1 if n == 1 else n * factorial(n-1)

print(factorial(5))  # 120
斐波那契数列
def fib(n):
    return n if n <= 1 else fib(n-1) + fib(n-2)

print([fib(i) for i in range(10)])
# [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

2.2 字符串处理

反转字符串
def reverse_str(s):
    return s if len(s) <= 1 else reverse_str(s[1:]) + s[0]

print(reverse_str("hello"))  # olleh
回文判断
def is_palindrome(s):
    if len(s) < 2:
        return True
    if s[0] != s[-1]:
        return False
    return is_palindrome(s[1:-1])

print(is_palindrome("madam"))  # True

三、数据结构处理

3.1 列表深度处理

def deep_sum(arr):
    total = 0
    for item in arr:
        if isinstance(item, list):
            total += deep_sum(item)
        else:
            total += item
    return total

nested_list = [1, [2, [3, 4], 5], 6]
print(deep_sum(nested_list))  # 21

3.2 字典树遍历

def traverse_tree(node, level=0):
    print('  '*level + node['name'])
    for child in node.get('children', []):
        traverse_tree(child, level+1)

tree = {
    'name': 'Root',
    'children': [
        {'name': 'Child1'},
        {'name': 'Child2', 
         'children': [
             {'name': 'Grandchild'}
         ]}
    ]
}

traverse_tree(tree)
"""
输出:
Root
  Child1
  Child2
    Grandchild
"""

四、经典算法实现

4.1 汉诺塔问题

def hanoi(n, source, target, auxiliary):
    if n > 0:
        hanoi(n-1, source, auxiliary, target)
        print(f"移动圆盘 {n}{source}{target}")
        hanoi(n-1, auxiliary, target, source)

hanoi(3, 'A', 'C', 'B')
"""
输出:
移动圆盘 1 从 A 到 C
移动圆盘 2 从 A 到 B
移动圆盘 1 从 C 到 B
移动圆盘 3 从 A 到 C
移动圆盘 1 从 B 到 A
移动圆盘 2 从 B 到 C
移动圆盘 1 从 A 到 C
"""

4.2 快速排序

def quicksort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[len(arr)//2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    return quicksort(left) + middle + quicksort(right)

print(quicksort([3,6,8,10,1,2,1]))  # [1, 1, 2, 3, 6, 8, 10]

五、高级递归技巧

5.1 记忆化优化

from functools import lru_cache

@lru_cache(maxsize=None)
def fibonacci(n):
    return n if n <= 1 else fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(50))  # 12586269025(无优化时无法计算)

5.2 尾递归优化

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

print(factorial(5))  # 120

六、递归调试技巧

6.1 调用栈可视化

def factorial_debug(n, depth=0):
    print(f"{'  '*depth}-> factorial({n})")
    if n == 1:
        result = 1
    else:
        result = n * factorial_debug(n-1, depth+1)
    print(f"{'  '*depth}<- {result}")
    return result

factorial_debug(3)
"""
输出:
-> factorial(3)
  -> factorial(2)
    -> factorial(1)
    <- 1
  <- 2
<- 6
"""

七、递归的替代方案

7.1 迭代实现

def factorial_iter(n):
    result = 1
    for i in range(1, n+1):
        result *= i
    return result

print(factorial_iter(5))  # 120

7.2 生成器实现

def traverse_tree_iter(node):
    stack = [(node, 0)]
    while stack:
        node, level = stack.pop()
        yield (node['name'], level)
        for child in reversed(node.get('children', [])):
            stack.append((child, level+1))

for name, level in traverse_tree_iter(tree):
    print('  '*level + name)

八、最佳实践与注意事项

8.1 适用场景

  • 树形结构处理
  • 分治算法
  • 数学递推公式
  • 回溯算法

8.2 风险规避

  1. 栈溢出风险(Python默认递归深度约1000层)
  2. 重复计算问题
  3. 时间复杂度失控
  4. 内存占用过高

8.3 性能优化方案

  1. 使用记忆化缓存(@lru_cache)
  2. 转换为迭代实现
  3. 尾递归优化(Python原生不支持,需自行实现)
  4. 限制递归深度
import sys

def safe_recursion(func):
    def wrapper(*args):
        wrapper.depth += 1
        if wrapper.depth > sys.getrecursionlimit() - 100:
            raise RecursionError("超出安全递归深度")
        try:
            return func(*args)
        finally:
            wrapper.depth -= 1
    wrapper.depth = 0
    return wrapper

@safe_recursion
def deep_recursion(n):
    return 1 if n == 0 else deep_recursion(n-1) + 1

九、递归思维训练

9.1 路径搜索问题

def find_path(matrix, start, end, path=[]):
    path = path + [start]
    if start == end:
        return [path]
    if matrix[start[0]][start[1]] == 0:
        return []
    paths = []
    for direction in [(0,1), (1,0), (0,-1), (-1,0)]:
        next_pos = (start[0]+direction[0], start[1]+direction[1])
        if 0 <= next_pos[0] < len(matrix) and \
           0 <= next_pos[1] < len(matrix[0]) and \
           next_pos not in path:
            newpaths = find_path(matrix, next_pos, end, path)
            paths += newpaths
    return paths

maze = [
    [1,1,0,1],
    [1,1,1,0],
    [0,1,1,1]
]
print(find_path(maze, (0,0), (2,3)))

十、总结提升

掌握递归不仅是学习编程技巧,更是培养抽象思维和问题分解能力的重要途径。合理运用递归,可以让复杂问题迎刃而解!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/963547.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于微信小程序的医院预约挂号系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

架构技能(四):需求分析

需求分析&#xff0c;即分析需求&#xff0c;分析软件用户需要解决的问题。 需求分析的下一环节是软件的整体架构设计&#xff0c;需求是输入&#xff0c;架构是输出&#xff0c;需求决定了架构。 决定架构的是软件的所有需求吗&#xff1f;肯定不是&#xff0c;真正决定架构…

【学习笔记】深度学习网络-正则化方法

作者选择了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰写的《Deep Learning》(人工智能领域的经典教程&#xff0c;深度学习领域研究生必读教材),开始深度学习领域学习&#xff0c;深入全面的理解深度学习的理论知识。 在之前的文章中介绍了深度学习中用…

c/c++高级编程

1.避免变量冗余初始化 结构体初始化为0&#xff0c;等价于对该内存进行一次memset&#xff0c;对于较大的结构体或者热点函数&#xff0c;重复的赋值带来冗余的性能开销。现代编译器对此类冗余初始化代码具有一定的优化能力&#xff0c;因此&#xff0c;打开相关的编译选项的优…

Vue 入门到实战 七

第7章 渲染函数 目录 7.1 DOM树 7.2 什么是渲染函数 7.3 h()函数 7.3.1 基本参数 7.3.2 约束 7.3.3 使用JavaScript代替模板功能 7.1 DOM树 7.2 什么是渲染函数 在多数情况下&#xff0c;Vue推荐使用模板template来创建HTML。然而在一些应用场景中&#xff0c;需要使用J…

小程序-基础加强-自定义组件

前言 这次讲自定义组件 1. 准备今天要用到的项目 2. 初步创建并使用自定义组件 这样就成功在home中引入了test组件 在json中引用了这个组件才能用这个组件 现在我们来实现全局引用组件 在app.json这样使用就可以了 3. 自定义组件的样式 发现页面里面的文本和组件里面的文…

MySQL5.5升级到MySQL5.7

【卸载原来的MySQL】 cmd打开命令提示符窗口&#xff08;管理员身份&#xff09;net stop mysql&#xff08;先停止MySQL服务&#xff09; 3.卸载 切换到原来5.5版本的bin目录&#xff0c;输入mysqld remove卸载服务 测试mysql -V查看Mysql版本还是5.5 查看了环境变量里的…

【memgpt】letta 课程4:基于latta框架构建MemGpt代理并与之交互

Lab 3: Building Agents with memory 基于latta框架构建MemGpt代理并与之交互理解代理状态,例如作为系统提示符、工具和agent的内存查看和编辑代理存档内存MemGPT 代理是有状态的 agents的设计思路 每个步骤都要定义代理行为 Letta agents persist information over time and…

DeepSeek-R1模型1.5b、7b、8b、14b、32b、70b和671b有啥区别?

deepseek-r1的1.5b、7b、8b、14b、32b、70b和671b有啥区别&#xff1f;码笔记mabiji.com分享&#xff1a;1.5B、7B、8B、14B、32B、70B是蒸馏后的小模型&#xff0c;671B是基础大模型&#xff0c;它们的区别主要体现在参数规模、模型容量、性能表现、准确性、训练成本、推理成本…

【TCP协议】流量控制 滑动窗口 拥塞控制

目录 说明&#xff1a; 流量控制 为什么要流量控制 什么是流量控制 如何控制流量&#xff1a;16位窗口大小 如果主机 B 一直没空间呢&#xff1f;标志位 PSH 滑动窗口&#xff1a;全面认识序号和确认序号 为什么需要滑动窗口&#xff1f; 理解滑动窗口 序号和确认序号…

K8S集群架构及主机准备

本次集群部署主机分布K8S集群主机配置主机静态IP设置主机名解析ipvs管理工具安装及模块加载主机系统升级主机间免密登录配置主机基础配置完后最好做个快照备份 2台负载均衡器 Haproxy高可用keepalived3台k8s master节点5台工作节点(至少2及以上)本次集群部署主机分布 K8S集群主…

三、js笔记

(一)JavaScript概述 1、发展历史 ScriptEase.(客户端执行的语言):1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase.(客户端执行的语言)Javascript:Netscape(网景)接收Nombas的理念,(Brendan Eich)在其Netscape Navigat…

穷举vs暴搜vs深搜vs回溯vs剪枝系列一>单词搜索

题解如下 题目&#xff1a;解析决策树&#xff1a;代码设计&#xff1a; 代码&#xff1a; 题目&#xff1a; 解析 决策树&#xff1a; 代码设计&#xff1a; 代码&#xff1a; class Solution {private boolean[][] visit;//标记使用过的数据int m,n;//行&#xff0c;列char…

使用Pygame制作“圣诞树”

1. 前言 圣诞节到来之际&#xff0c;来给自己写一个圣诞树小动画吧&#xff01;我们可以利用 Pygame 的绘图功能&#xff0c;轻松地在 2D 屏幕上绘制各种几何形状&#xff0c;并为圣诞树加上灯光闪烁、装饰品等效果。本篇将带领你实现一个简易版本的“屏幕圣诞树”&#xff0c…

Windows电脑本地部署运行DeepSeek R1大模型(基于Ollama和Chatbox)

文章目录 一、环境准备二、安装Ollama2.1 访问Ollama官方网站2.2 下载适用于Windows的安装包2.3 安装Ollama安装包2.4 指定Ollama安装目录2.5 指定Ollama的大模型的存储目录 三、选择DeepSeek R1模型四、下载并运行DeepSeek R1模型五、使用Chatbox进行交互5.1 下载Chatbox安装包…

《AI大模型开发笔记》DeepSeek技术创新点

一、DeepSeek横空出世 DeepSeek V3 以颠覆性技术架构创新强势破局&#xff01;革命性的上下文处理机制实现长文本推理成本断崖式下降&#xff0c;综合算力需求锐减90%&#xff0c;开启高效 AI 新纪元&#xff01; 最新开源的 DeepSeek V3模型不仅以顶尖基准测试成绩比肩业界 …

【深度学习】softmax回归的从零开始实现

softmax回归的从零开始实现 (就像我们从零开始实现线性回归一样&#xff0c;)我们认为softmax回归也是重要的基础&#xff0c;因此(应该知道实现softmax回归的细节)。 本节我们将使用Fashion-MNIST数据集&#xff0c;并设置数据迭代器的批量大小为256。 import torch from IP…

python学opencv|读取图像(五十二)使用cv.matchTemplate()函数实现最佳图像匹配

【1】引言 前序学习了图像的常规读取和基本按位操作技巧&#xff0c;相关文章包括且不限于&#xff1a; python学opencv|读取图像-CSDN博客 python学opencv|读取图像&#xff08;四十九&#xff09;原理探究&#xff1a;使用cv2.bitwise()系列函数实现图像按位运算-CSDN博客…

如果通过认证方式调用Sf的api

导读 OAuth 2.0:是一个开放的授权框架&#xff0c;当用户想要访问Service Provider提供的资源时&#xff0c;OAuth客户端可以从IdP(Identity Provider)获得授权而不需要获取用户名和密码就可以访问该资源题。 作者&#xff1a;vivi&#xff0c;来源&#xff1a;osinnovation …

SpringBoot 整合 SpringMVC:SpringMVC的注解管理

分类&#xff1a; 中央转发器(DispatcherServlet)控制器视图解析器静态资源访问消息转化器格式化静态资源管理 中央转发器&#xff1a; 中央转发器被 SpringBoot 自动接管&#xff0c;不需要我们在 web.xml 中配置&#xff1a; <servlet><servlet-name>chapter2&l…