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

递归动漫讲解咯

递归的回归逻辑

代码示例

#include "stdlib.h"#include "stdio.h"// 如何按照字典序进行输出 枚举int arr[10];// 打印函数void print_one_result(int n) {// 遍历for (int i = 0; i <= n; i++) {if (i) {printf(" ");}printf("%d", arr[i]);}printf("\n");}​/**** @param i 起始索引* @param j 跟踪当前数* @param n 边界数*/// 递归函数void f(int i, int j, int n) {// p(1) = j > nif (j > n) {return;}// p(n) =for (int k = j; k <= n; k++) {arr[i] = k;print_one_result(i);f(i + 1, k + 1, n);}}int main() {int n;scanf("%d", &n);f(0, 1, n);return 0;}

讲解

我们换一种超级通俗、有趣、细节拉满的方式,把这个递归代码讲透!

把自己想象成一个导演,正在拍一部叫做《递归探险记》的电影。


电影名称:《递归探险记》

主演

  • :扮演递归函数 f

  • 小助手print_one_result,负责在你发现宝藏时拍照记录。

  • 宝藏数组 arr:一个神奇的盒子,用来存放你一路上找到的宝藏(数字)。

  • 总导演main 函数,他只负责喊“开始!”。

故事背景:你需要按字典序(就是字典里单词的排序方式,比如 "1" 排在 "1 2" 前面, "1 2" 排在 "1 3" 前面)探索所有从 1n 的数字组合。每找到一个组合,小助手就会拍一张照片记录下来。

你的装备(函数参数)

  • i:你当前所在的位置(比如第 i 个藏宝点)。

  • j:你下一步可以选择的最小数字(为了保证字典序和不重复,你不能回头选更小的数字)。

  • n:地图的边界,数字不能超过 n

你的任务(函数 f 的代码逻辑)

  1. 检查边界:如果 j > n,说明你已经走到地图外面了,这条路不通,立即返回

  2. 循环探索:从你可以选择的最小数字 j 开始,一直到地图边界 n:a. 放置宝藏:把当前数字 k 放进宝藏数组 arr 的第 i 个位置。b. 拍照留念:喊小助手 print_one_result(i) 过来,把当前 arr 盒子里从第0个位置到第 i 个位置的宝藏拍下来。c. 派遣分身克隆一个自己(递归调用 f),让他去探索下一个位置 i+1。并且告诉他,他只能从比你当前数字 k1 的数字(k+1)开始选,这样才能保证顺序。d. 分身回归:你的克隆人探索完回来后,你继续尝试下一个数字(k 增加1)。

    能力明确:你可以分身,但是你每次只能控制一个身体,因为你只有一个灵魂,大多数情况下你分身都得先把行动明确好,回归后分身可能要继续完成行动再回归,直到最后完全还魂,你就利用完分身啦!

    补充声明:fn代表i=n


开拍(递进)!以 n=3 为例

总导演 main:“Action!f(0, 1, 3)!”

第一幕:你(f0)的探险
  • f0):装备 i=0, j=1, n=3

  • :检查 j=1 是否大于 n=3?不大于。开始循环 k13

场景 1a:k=1

  • :把 1 放进 arr[0]。现在 arr 盒子里是 [1, ?, ?]

  • :“小助手,拍照!”

  • 小助手:咔嚓!拍下来 1,打印出来。

  • :“我需要一个分身去下一个位置!”

    • 你克隆了自己(我们叫他 f1)。

    • f1 说:“f1,你去位置 i=1,记住,你只能从 k+1=2 开始选数字,总边界还是 3。”

    • f0)现在暂停,等待 f1 回来。

第二幕:分身 f1 的探险
  • 分身 f1:装备 i=1, j=2, n=3

  • f1:检查 j=2 是否大于 n=3?不大于。开始循环 k23

场景 2a:k=2

  • f1:把 2 放进 arr[1]。现在 arr 盒子里是 [1, 2, ?]

  • f1:“小助手,拍照!”

  • 小助手:咔嚓!拍下来 1 2,打印出来。

  • f1:“我也需要一个分身!”

    • f1 克隆了自己(我们叫他 f2)。

    • f1f2 说:“f2,你去位置 i=2,从 k+1=3 开始选,总边界 3。”

    • f1 现在暂停,等待 f2 回来。

第三幕:分身的分身 f2 的探险
  • 分身 f2:装备 i=2, j=3, n=3

  • f2:检查 j=3 是否大于 n=3?不大于。开始循环 k33

场景 3a:k=3

  • f2:把 3 放进 arr[2]。现在 arr 盒子里是 [1, 2, 3]

  • f2:“小助手,拍照!”

  • 小助手:咔嚓!拍下来 1 2 3,打印出来。

  • f2:“我也需要一个分身去下一个位置!”

    • f2 克隆了自己(我们叫他 f3)。

    • f2f3 说:“f3,你去位置 i=3,从 k+1=4 开始选,总边界 3。”

    • f2 现在暂停,等待 f3 回来。

第四幕:最深的分身 f3 的探险
  • 分身 f3:装备 i=3, j=4, n=3

  • f3:检查 j=4 是否大于 n=3是的!

  • f3:“报告!前面没路了!” 说完,f3 直接消失了(return)。


还魂(回归)的时刻开始了!

回归到 f2
  • f2 一直在等 f3,突然 f3 消失了,f2 知道 f3 探索完了。

  • f2 的循环 k33 也执行完毕了。

  • f2:“我的任务完成了!” 说完,f2 也消失了,并把控制权交还给了 f1

f2 回归前后数据对比:

  • 回归前 (即 f2 调用 f3 之前的状态):

    • f2 的装备:i=2, j=3, k=3

    • arr 盒子:[1, 2, 3]

  • 回归后 (即 f3 返回,f2 继续执行之后的状态):

    • f2 的循环 k 已经执行完(k 变成了 4)。

    • f2 函数执行完毕,准备消失。

    • arr 盒子:[1, 2, 3] (因为 f3 没修改它)。

    • 程序回到 f1 调用 f2 的地方,f1 准备继续执行。

回归到 f1
  • f1 一直在等 f2,突然 f2 消失了,f1 知道 f2 探索完了。

  • f1 的循环继续,k2 增加到 3

场景 2b:k=3 (这是 f1 循环的下一次迭代)

  • f1:把 3 放进 arr[1]注意! 这里 arr[1] 的值被覆盖了。现在 arr 盒子里是 [1, 3, ?]

  • 广告:其实这里的?是3,只是小助手可以拍照的范围被限制了!

  • f1:“小助手,拍照!”

  • 小助手:咔嚓!拍下来 1 3,打印出来。

  • f1:“再派一个分身!”

    • f1 又克隆了自己(我们叫他 f4)。

    • f1f4 说:“f4,你去位置 i=2,从 k+1=4 开始选,总边界 3。”

    • f1 再次暂停,等待 f4 回来。

第五幕:分身 f4 的探险
  • 分身 f4:装备 i=2, j=4, n=3

  • f4:检查 j=4 是否大于 n=3是的!

  • f4:“报告!没路了!” 说完,f4 消失了。

再次回归到 f1
  • f1f4 消失后,它的循环 k33 也执行完毕了。

  • f1:“我的任务也完成了!” 说完,f1 消失了,把控制权交还给了你(f0)。

f1 回归前后数据对比 (第二次回归):

  • 回归前 (即 f1 调用 f4 之前的状态):

    • f1 的装备:i=1, j=2, k=3

    • arr 盒子:[1, 3, ?]

  • 回归后 (即 f4 返回,f1 继续执行之后的状态):

    • f1 的循环 k 已经执行完(k 变成了 4)。

    • f1 函数执行完毕,准备消失。

    • arr 盒子:[1, 3, ?] (因为 f4 没修改它)。

    • 程序回到 f0 调用 f1 的地方,f0 准备继续执行。

回归到你(f0
  • 你(f0)一直在等 f1,突然 f1 消失了,你知道 f1 探索完了。

  • 你的循环继续,k1 增加到 2

场景 1b:k=2 (这是 f0 循环的下一次迭代)

  • :把 2 放进 arr[0]注意! arr[0] 的值被覆盖了。现在 arr 盒子里是 [2, ?, ?]

  • :“小助手,拍照!”

  • 小助手:咔嚓!拍下来 2,打印出来。

  • :“派一个分身去 i=1,从 k+1=3 开始!”

    • 这个新分身 f5 的故事和之前类似,他会发现 2 3,然后他的分身 f6 会发现没路。

    • f6 回归 → f5 回归 → 回到你这里。

你的循环继续,k 增加到 3,然后是 k=3 的场景,最后你的循环也结束了。

最终回归
  • 你(f0)的所有任务都完成了,你也消失了。

  • 程序控制权回到总导演 main 那里。

  • main:“Cut!完美收官!”

总结一下“回归”的魔法

  1. 暂停与等待:当你(一个函数调用)派遣一个分身(递归调用)时,你自己就暂停了,进入“等待”状态。

  2. 独立的探险:你的分身有他自己的一套装备(参数 i, j, n)和他自己的循环变量 k。他的探险是独立的。

  3. 回归即恢复:当分身探险结束(return),他就消失了。这时,在你暂停的地方恢复执行。你继续你刚才没完成的循环,k 的值还是你暂停时的值(然后会自增)。

  4. 共享的宝藏盒arr 数组是大家共享的。当一个分身修改了它,后面的分身(或回归后的你)看到的就是修改后的值。这就是为什么序列会不断变化。

整个过程就像一群探险家在走一个分叉很多的迷宫,每个人走到一个路口就派一个队友去探索一条支路,自己则在路口等着。当队友探路回来报告“此路不通”或“已探索完毕”,这个人就继续探索下一条支路。最终,所有可能的路径都被探索过,所有宝藏组合都被记录下来了。

http://www.dtcms.com/a/589998.html

相关文章:

  • 男和男做的视频网站宿迁房产网签备案查询系统
  • 好用的Windows工具
  • 公司发布网站需要备案吗专业的建网站公司地址
  • C++ 从入门到进阶:核心知识与学习指南
  • 怎么获得免费网站首饰设计网站推荐
  • 做网站是买服务器还是买cdn微信页面
  • 网上书城网站开发自学网站开发软件开发
  • 门户网站广告的类型wordpress 修改字体
  • 混合式教学财务管理网站建设网站 设计案例
  • 搭建LNMP私有云存储
  • Zabbix监控K8S的PV卷
  • 电商网站开发视频中国最厉害的营销策划公司
  • MyBatis-Plus 通用 CRUD 实现原理技术文档
  • 通俗易懂:YOLO模型原理详解,从零开始理解目标检测
  • 织梦 和wordpress建站seo是什么
  • GRNN广义回归神经网络分类预测+特征贡献SHAP分析+特征依赖图!Matlab
  • 深度学习周报(11.3~11.9)
  • 【MySQL】数据库基本知识
  • 连云港网站关键字优化如何网络营销环境分析包括哪些内容
  • 网站建设语言都有什么广东外贸网站推广
  • 临沂建网站公司网站切图是指什么
  • 不用写代码做网站软件飞狐小说网站建设
  • wdcp拒绝访问网站企业网站本身应该就是企业( )的一部分
  • 子数组|状态机dp
  • 家居网站建设如何自己公司网站维护
  • Spring Boot 3+Spring AI 打造旅游智能体!集成阿里云通义千问,多轮对话 + 搜索 + PDF 生成撑全流程
  • 西安网站设计制作一般多少钱新媒体营销的发展趋势
  • 手机T0智能算法交易个人开通指南
  • 卢沟桥网站建设互联网舆情报告
  • 4.2 Boost 库工具类 ignore_unused 的使用