当前位置: 首页 > article >正文

深入理解递归:从原理到C++实践

什么是递归?

递归(Recursion)是编程中一种强大的技术,其核心思想是:函数直接或间接地调用自身。如同俄罗斯套娃一般,每个函数调用都会解开问题的一个层级,直到达到基础条件。

递归三要素:

基准条件(Base Case):递归终止的条件

递归关系(Recursive Relation):问题分解的规律

向基准条件推进:每次递归调用必须接近基准条件

递归通过调用栈(Call Stack)实现:

递归执行原理:

每次递归调用将新状态压入栈

达到基准条件后开始出栈

依次执行后续代码(回溯阶段)

C++示例

示例1 阶乘计算

#include <iostream>int factorial(int n) {// 基准条件if (n == 0 || n == 1)return 1;// 递归关系:n! = n * (n-1)!return n * factorial(n - 1);
}int main() {std::cout << "5! = " << factorial(5) << std::endl; // 输出120return 0;
}

输出:

factorial(5)
5 * factorial(4)
5 * (4 * factorial(3))
5 * (4 * (3 * factorial(2)))
5 * (4 * (3 * (2 * factorial(1))))
5 * (4 * (3 * (2 * 1))) = 120

示例2:斐波那契数列

#include <iostream>int fibonacci(int n) {if (n <= 1)return n;return fibonacci(n-1) + fibonacci(n-2);
}int main() {std::cout << "第7项:" << fibonacci(7) << std::endl; // 输出13return 0;
}

在这里插入图片描述

示例3:目录遍历(模拟实现)

#include <iostream>
#include <vector>struct File {std::string name;bool is_directory;std::vector<File> children;
};void traverse(const File& entry, int depth = 0) {// 打印缩进std::cout << std::string(depth*2, ' ');if(entry.is_directory) {std::cout << "[DIR] " << entry.name << std::endl;for(const auto& child : entry.children) {traverse(child, depth+1);}} else {std::cout << entry.name << std::endl;}
}int main() {File root = {"Root", true, {{"Document", true, {{"resume.doc", false, {}},{"photo.jpg", false, {}}}},{"Program", true, {{"main.cpp", false, {}},{"README.md", false, {}}}}}};traverse(root);return 0;
}

输出
在这里插入图片描述

递归的注意事项

栈溢出风险:

深度递归可能导致栈溢出

解决方法:改用迭代或尾递归优化

重复计算问题:

斐波那契示例中的低效计算

解决方法:记忆化(Memoization)

性能考量:

递归的时间/空间复杂度通常较高
比较:迭代 vs 递归

调试技巧:

使用调试器观察调用栈
打印递归深度和参数值

何时使用递归?

✅ 适合场景:

问题具有自然递归结构(树形结构、分治算法)

代码可读性优先的场景

问题规模可预测且深度可控

❌ 避免场景:

性能关键路径
递归深度可能很大的情况
需要频繁调用的基础功能

压栈和出栈示例

#include<iostream>void countdown(int n);int main()
{countdown(4);return 0;
}void countdown(int n)
{std::cout<<"Counting down ...." <<n<< std::endl;if (n > 0){countdown(n - 1);}std::cout << n << ":Kaboom!\n" << std::endl;
}

输出:
在这里插入图片描述

递归调用阶段(压栈)

在这里插入图片描述

递归返回阶段(弹栈)

在这里插入图片描述

关键特点

栈帧内容:

每个栈帧保存:
函数参数(如 n 的值)
返回地址(调用后的代码位置)
局部变量(若有)

后进先出(LIFO):

最后调用的 countdown(0) 最先完成
先调用的 countdown(4) 最后完成

空间复杂度:

递归深度为 O(n),本例中栈空间占用与 n=4 成正比

栈溢出风险:

若递归深度过大(如 n=100000),会导致栈溢出(Stack Overflow)

在这里插入图片描述

为什么 “Kaboom!” 是逆序输出的?

因为递归的 回溯阶段(Unwinding) 遵循后进先出原则:

最后调用的 countdown(0) 最先执行 Kaboom! 输出

最早调用的 countdown(4) 最后执行 Kaboom! 输出

通过这种栈内存变化模型,可以清晰理解递归的 双向特性:

递:不断分解问题(压栈)

归:组合子问题的解(弹栈)

相关文章:

深入理解递归:从原理到C++实践

什么是递归&#xff1f; 递归&#xff08;Recursion&#xff09;是编程中一种强大的技术&#xff0c;其核心思想是&#xff1a;函数直接或间接地调用自身。如同俄罗斯套娃一般&#xff0c;每个函数调用都会解开问题的一个层级&#xff0c;直到达到基础条件。 递归三要素&…...

【2025年15期免费获取股票数据API接口】实例演示五种主流语言获取股票行情api接口之沪深A股解禁限售数据获取实例演示及接口API说明文档

在近一至两年期间&#xff0c;股票量化分析逐步成为备受关注的热门议题。对于投身于该领域工作而言&#xff0c;首要步骤便是获取全面且精准的股票数据。无论是实时交易数据、历史交易记录、财务数据&#xff0c;亦或是基本面信息&#xff0c;这些数据均是开展量化分析过程中不…...

MyBatis-Plus 入门详解:从零搭建高效持久层

一、MyBatis-Plus 简介 MyBatis-Plus&#xff08;简称 MP&#xff09;是 MyBatis 的增强工具&#xff0c;在保留 MyBatis 原生功能的基础上&#xff0c;提供了全自动化的 CRUD 操作、强大的分页插件、代码生成器等功能&#xff0c;显著减少开发工作量。与原生 MyBatis 相比&…...

阿里云物联网获取设备属性api接口:QueryDevicePropertyData

阿里云物联网接口&#xff1a;QueryDevicePropertyData 说明&#xff1a;调用该接口查询指定设备或数字孪生节点&#xff0c;在指定时间段内&#xff0c;单个属性的数据 比如提取上传到物联网的温度数据 api文档&#xff1a;QueryDevicePropertyData_物联网平台_API文档-阿里…...

歌曲分类和流行度预测

1. 项目介绍 本项目从kaggle平台上下载了数据集&#xff0c;该数据集包含了3万多首来自Spotify API 的歌曲&#xff0c;共有23个特征。首先对数据集进行预处理&#xff0c;如重复行、缺失值、标准化处理等。再对预处理后的数据进行探索性分析&#xff0c;观察各变量的分布情况&…...

不重启mysql情况下排查慢SQL

查状态 mysql> show variables like %slow_query_log%; 开启慢日志 mysql> set global slow_query_logON; 设置1s超时 mysql> set global long_query_time1; 如果想更小&#xff0c;可以设置0.5 查看慢SQL的日志 cat /var/lib/mysql/localhost-slow.log &…...

27、Java 反射机制

15-1 Java 反射机制概述 Reflection&#xff08;反射&#xff09;是被视为动态语言的关键 动态语言&#xff1a;在运行时代码可以根据某些条件改变自身结构。如 C#\JavaScript\PHP 静态语言&#xff1a;运行时结构不可变的语言。如 Java\C\C 问题&#xff1a;通过直接new的方…...

【开源项目】好用的开源项目记录(持续更新)

注意&#xff1a;在使用开源软件的时候&#xff0c;一定要注意代码中是否含有可疑代码&#xff0c;黑客代码&#xff0c;后门漏洞 1、爬虫工具 https://gitee.com/ssssssss-team/spider-flow 参考使用方式&#xff1a;https://blog.csdn.net/qq_42640067/article/details/12059…...

Android 端侧运行 LLM 框架 MNN 及其应用

MNN Chat Android App - 基于 MNN 引擎的智能聊天应用 一、MNN 框架简介与工作原理1.1 什么是 MNN&#xff1f;1.2 MNN 的工作原理 二、MNN Chat Android App2.1 MNN Chat 的功能2.2 MNN Chat 的优势2.3 MNN Chat Android App 的使用 三、总结 随着移动端人工智能需求的日益增长…...

FPGA学习(一) —— 四位全加器

FPGA学习&#xff08;一&#xff09; —— 四位全加器 文章目录 FPGA学习&#xff08;一&#xff09; —— 四位全加器一、半加器1、半加器的真值表2、Verilog代码实现3、RTL原理图4、波形仿真 二、一位全加器1、一位全加器真值表2、Verilog代码实现3、RTL原理图4、波形仿真 三…...

PHP:IDEA开发工具配置XDebug,断点调试

文章目录 一、php.ini配置二、IDEA配置 一、php.ini配置 [xdebug] zend_extension"F:\wamp64\bin\php\php7.4.0\ext\php_xdebug-2.8.0-7.4-vc15-x86_64.dll" xdebug.remote_enable on xdebug.remote_host 127.0.0.1 xdebug.remote_port 9001 xdebug.idekey"…...

LINUX网络基础 - 网络编程套接字,UDP与TCP

目录 前言 一. 端口号的认识 1.1 端口号的作用 二. 初识TCP协议和UDP协议 2.1 TCP协议 TCP的特点 使用场景 2.2 UDP协议 UDP的特点 使用场景 2.3 TCP与UDP的对比 2.4 思考 2.5 总结 三. 网络字节序 3.1 网络字节序的介绍 3.2 网络字节序思考 四. socket接口 …...

iOS UICollectionViewCell 点击事件自动化埋点

iOS 中经常要进行埋点&#xff0c;我们这里支持 UICollectionViewCell. 进行自动化埋点&#xff0c;思路&#xff1a; 通过hook UICollectionViewCell 的setSelected:方法&#xff0c; 则新的方法中执行埋点逻辑&#xff0c;并调用原来的方法 直接上代码 implementation UICol…...

QT实现单个控制点在曲线上的贝塞尔曲线

最终效果: 一共三个文件 main.cpp #include <QApplication> #include "SplineBoard.h" int main(int argc,char** argv) {QApplication a(argc, argv);SplineBoard b;b.setWindowTitle("标准的贝塞尔曲线");b.show();SplineBoard b2(0.0001);b2.sh…...

Linux基础开发工具(vim编译器,yum与apt软件安装)

Linux 下载安装软件的方案 源代码安装-》》》非常麻烦与复杂一步错步步错 rmp包安装 -》》》只是安装没有对应的库与依赖相当于只是一个外壳 包管理器进行安装-》》 yum / apt(本篇重点讲解) 1.什么是软件包和软件包管理器 就好⽐ "App" 和 "应⽤商店"…...

神经网络 - 激活函数(Maxout 单元)

一、Maxout 单元 Maxout 单元是一种特殊的激活函数&#xff0c;用于神经网络中&#xff0c;其主要思想是通过多个线性变换的最大值来作为神经元的输出&#xff0c;从而提高模型的表达能力和鲁棒性。 1. 数学定义 假设输入为 x&#xff0c;Maxout 单元会计算 k 个线性变换&am…...

nginx+keepalived负载均衡及高可用

1 项目背景 keepalived除了能够管理LVS软件外&#xff0c;还可以作为其他服务的高可用解决方案软件。采用nginxkeepalived&#xff0c;它是一个高性能的服务器高可用或者热备解决方案&#xff0c;Keepalived主要来防止服务器单点故障的发生问题&#xff0c;可以通过其与Nginx的…...

6.人工智能与机器学习

一、人工智能基本原理 1. 人工智能&#xff08;AI&#xff09;定义与范畴 核心目标&#xff1a;模拟人类智能行为&#xff08;如推理、学习、决策&#xff09;分类&#xff1a; 弱人工智能&#xff08;Narrow AI&#xff09;&#xff1a;专精单一任务&#xff08;如AlphaGo、…...

VirtualBox虚拟机转VM虚拟机

前言&#xff1a;部分靶机只适用于VirtualBox&#xff0c;VM打不开VirtualBox的文件&#xff0c;所以需要进行转换 前置条件&#xff1a;本机已经下载VM和VirtualBox 第一步&#xff1a;文件转换 找到VirtualBox.exe所在位置&#xff0c;启动cmd窗口 文件转换的命令&#xf…...

谈谈 HTTPS 的工作原理,SSL / TLS 握手流程是什么?

一、HTTPS 核心机制&#xff1a;非对称加密 对称加密 HTTPS HTTP over TLS/SSL&#xff0c;通过 ​混合加密体系​ 解决三大问题&#xff1a; ​防窃听​ - 对称加密传输内容&#xff08;如 AES&#xff09;​防篡改​ - 数字签名验证数据完整性​防冒充​ - 数字证书验证服…...

使用DeepSeek+KIMI生成高质量PPT

一、使用DeepSeek DeepSeek官网&#xff1a;DeepSeek 点击“开始对话”&#xff0c;进入交互页面。 在上图中&#xff0c;输入问题&#xff0c;即可获取AI生成的结果。 基础模型&#xff08;V3&#xff09;&#xff1a;通用模型&#xff08;2024.12&#xff09;&#xff0c;高…...

基于SpringBoot的失物招领平台的设计与实现

基于SpringBoot的失物招领平台的设计与实现 基于微信小程序的失物招领系统 失物招领小程序 校园失物招领小程序 基于微信小程序SSMMySQL开发&#xff0c;高分JAVA成品毕业设计&#xff0c;附带往届论文、启动教程、讲解视频、二次开发教程和配套安装包文件&#xff0c;论文中…...

鸿蒙NEXT开发-元服务和服务卡片的开发

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙next相关知识 目录 1. 元服务基本概念 1.1 基本介绍 1.2 元…...

【Spark+Hive】基于Spark大数据技术小红书舆情分析可视化预测系统(完整系统源码+数据库+开发笔记+详细部署教程+虚拟机分布式启动教程)✅

目录 一、项目背景 二、项目目标 三、算法介绍 四、开发技术介绍 五、项目创新点 六、项目展示 七、权威教学视频 源码获取方式在文章末尾 一、项目背景 在数字经济蓬勃发展的当下&#xff0c;社交电商平台小红书凭借其"内容电商"的独特模式&#xff0c;已…...

IO基础知识和练习

一、思维导图 二、练习 1.使用标准IO函数&#xff0c;实现文件的拷贝 #include <head.h> int main(int argc, const char *argv[]) {FILE *pfopen("./one.txt","r");FILE *fpfopen("./two.txt","r");if(pNULL)PRINT_ERROR(&qu…...

gradle libs.versions.toml文件

1.libs.versions.toml介绍2.创建libs.versions.toml文件3.libraries5.versions6.plugins7.bundles 1.libs.versions.toml介绍 下图是官网介绍 意思就是说项目所有插件和库的依赖版本都统一在这个文件配置。 文件中有以下四个部分 versions, 申明要使用的插件和库的版本号的…...

影刀RPA开发拓展--SQL常用语句全攻略

前言 SQL&#xff08;结构化查询语言&#xff09;是数据库管理和操作的核心工具&#xff0c;无论是初学者还是经验丰富的数据库管理员&#xff0c;掌握常用的 SQL 语句对于高效管理和查询数据都至关重要。本文将系统性地介绍最常用的 SQL 语句&#xff0c;并为每个语句提供详细…...

2024_BUAA数据结构上机题解分享

&#x1f4ce; GitHub/Gitee同步开源 | &#x1f680; 点击访问Gitee仓库 点击访问GitHub仓库 &#xff08;若访问缓慢可尝试切换仓库镜像源&#xff09; 这份代码库不是捷径&#xff0c;而是北航数据结构的生存地图。当你被困在递归迷雾中时&#xff0c;愿这些经过OJ系统千锤百…...

什么是分布式和微服务?

一、分布式系统 定义&#xff1a; 分布式系统是由多个独立的计算节点&#xff08;或称为服务器、计算机&#xff09;通过网络相互连接&#xff0c;共同协作以完成特定任务的系统。这些节点可以运行在不同的物理服务器或虚拟机上。 核心思想&#xff1a; 提高系统的可扩展性&am…...

2025 Lakehouse 趋势全景展望:从技术演进到商业重构

1. 为什么湖仓正在成为企业数据架构的必选项&#xff1f; 越来越多的企业正在通过实时数据处理能力构建核心竞争力——用户期待 APP 精准捕捉需求并实时响应&#xff0c;企业员工追求业务系统的秒级反馈&#xff0c;这些场景背后是千亿级数据资产的敏捷调度。 据 IDC 预测&am…...