人理解迭代,而神理解递归————递归思想心得

本文深入探讨了递归的概念,通过比较递归与循环的区别,阐述了递归的核心思想——有递去有归来。递归的关键在于明确终止条件、处理简单情境及提取重复逻辑。递归在数学归纳法中也有体现,适合解决相同逻辑的子问题。文中还介绍了编写递归程序的两个编程模型,并提供了实际问题的应用示例。

        一、递归(Recursion),顾名思义,有递去有归来。在编程中,最常见的就是总问题与其子问题的思路完全一致,即解决了该子问题,总问题也就迎刃而解。

        有人会问,递归与循环有什么区别呢?递归也是把子问题一个一个的解决,总问题也就解决了,与循环思想差不多啊?通俗点讲:

        递归:你打开面前这扇门,看到屋里面还有一扇门。你走过去,发现手中的钥匙还可以打开它,你推开门,发现里面还有一扇门,你继续打开它。若干次之后,你打开面前的门后,发现只有一间屋子,没有门了。然后,你开始原路返回,每走回一间屋子,你数一次,走到入口的时候,你可以回答出你到底用这你把钥匙打开了几扇门。

   循环:你打开面前这扇门,看到屋里面还有一扇门。你走过去,发现手中的钥匙还可以打开它,你推开门,发现里面还有一扇门(若前面两扇门都一样,那么这扇门和前两扇门也一样;如果第二扇门比第一扇门小,那么这扇门也比第二扇门小,你继续打开这扇门,一直这样继续下去直到打开所有的门。但是,入口处的人始终等不到你回去告诉他答案。

        好了,说回之前的“有递去有归来”的思想。

        递去:将总问题从前向后,一个一个分解为相同的子问题。

        归来:遇到终止条件后(终止条件必须明确,否则会出现无限递归,锁死),开始将子问题一个一个按倒序解决

由于总问题与子问题的解决方法完全一致,所以会出现函数调用自身的情况。

        二、我们在初中都学过“数学归纳法”。用“数学归纳法”的思想去理解递归也不错:

数学归纳法:
1.i = 0,i = 1时,结论成立
2.若i = n时,结论仍旧成立,则i = n+1时,结论亦成立

数学归纳法是正确的递归思考方式,第 1 点称为基本情况,第 2 点称为通用情况。

数学归纳法适用于将解决的原问题转化为解决它的子问题,而它的子问题又变成子问题的子问题,而且我们发现这些问题其实都是一个模型,也就是说存在相同的逻辑归纳处理项。当然有一个是例外的,也就是归纳结束的那一个处理方法不适用于我们的归纳处理项,当然也不能适用,否则我们就无穷归纳了。

总的来说,归纳法主要包含以下三个关键要素:

1)步进表达式:问题蜕变成子问题的表达式 
2)结束条件:什么时候可以不再使用步进表达式 
3)直接求解表达式:在结束条件下能够直接计算返回值的表达式 
事实上,这也正是某些数学中的数列问题在利用编程的方式去解决时可以使用递归的原因,比如著名的斐波那契数列问题。

        三、递归的三要素

   在我们了解了递归的基本思想及其数学模型之后,我们如何才能写出一个漂亮的递归程序呢?笔者认为主要是把握好如下三个方面:

1、明确递归终止条件;

2、给出递归终止时的处理办法;

3、提取重复的逻辑,缩小问题规模。

1). 明确递归终止条件

   我们知道,递归就是有去有回,既然这样,那么必然应该有一个明确的临界点,程序一旦到达了这个临界点,就不用继续往下递去而是开始实实在在的归来。换句话说,该临界点就是一种简单情境,可以防止无限递归。

2). 给出递归终止时的处理办法

   我们刚刚说到,在递归的临界点存在一种简单情境,在这种简单情境下,我们应该直接给出问题的解决方案。一般地,在这种情境下,问题的解决方案是直观的、容易的。

3). 提取重复的逻辑,缩小问题规模*

   我们在阐述递归思想内涵时谈到,递归问题必须可以分解为若干个规模较小、与原问题形式相同的子问题,这些子问题可以用相同的解题思路来解决。从程序实现的角度而言,我们需要抽象出一个干净利落的重复的逻辑,以便使用相同的方式解决子问题

        四、建立编程模型

模型一:递去过程中解决问题


function recursion(大规模){
    if (end_condition){      // 明确的递归终止条件
        end;   // 简单情景
    }else{            // 在将问题转换为子问题的每一步,解决该步中剩余部分的问题
        solve;                // 递去
        recursion(小规模);     // 递到最深处后,不断地归来
    }
}

模型二:归来过程中解决问题


function recursion(大规模){
    if (end_condition){      // 明确的递归终止条件
        end;   // 简单情景
    }else{            // 先将问题全部描述展开,再由尽头“返回”依次解决每步中剩余部分的问题
        recursion(小规模);     // 递去
        solve;                // 归来
    }
}

本文有参考下面文章的思路,笔者也是根据下面的文章学习的递归思想

递归算法的讲解_jacklin_01的博客-优快云博客_递归详解

例题请看:Leetcode刷题心得(No.24:两两交换链表中的结点)(三指针,递归)_FightingCSH的博客-优快云博客

实验项目 实验四:函数 实验目的 1.理解并掌握 Python 函数的定义、调用方法与参数传递机制。 2.掌握递归函数的设计思想及其在实际问题(如汉诺塔)中的应用。 3.掌握匿名函数(lambda)和高阶函数在程序设计中的使用方法。 4.综合运用函数相关知识,完成一个简易学生管理系统的功能设计与实现。 实验内容 1.递归函数应用——汉诺塔问题 2.综合应用——学生管理系统 步骤 一、1.汉诺塔是一个源于印度古老传说的益智玩具,有3根柱子(命名为A、B、C)和个大小不同的圆盘(从小到大编号为1~n),圆盘中间有孔,可以穿在任何一个柱子上假设最开始圆盘从下往上从大到小穿在A柱上,利用B柱做中转,将圆盘从A移动到C柱,移动过程需要注意: (1)每次只能移动一个圆盘; (2)圆盘只能从一个柱子的顶端移动到另一个柱子; (3)圆盘只能移动到比它大的圆盘上,也就是任何时候每根柱子从下往上都是从大到小编号的圆盘。 假设n=5,请使用递归函数编程解决汉诺塔问题。每一步可以输出类似"圆盘1从A->B”这样的信息",用来说明最顶端的1号圆盘从A柱移动到B柱。 1)代码 2)运行结果及截图 3)代码及运行结果分析(请结合以下要点进行分析:代码实现思路和关键技术点、运行结果的正确性分析、实验过程中的问题及解决方法、个学习心得和改进建议等) 二、完成设计一个简易的Python学生管理系统。(按照PPT中要求及示例完成,每个功能都需要有对应截图展示) 1)代码 2)运行结果及截图 3)代码及运行结果分析(请结合以下要点进行分析:代码实现思路和关键技术点、运行结果的正确性分析、实验过程中的问题及解决方法、个学习心得和改进建议等) 根据以上要求完成两题的代码 写出来不要像ai写的
最新发布
11-29
# 题目重述 本实验包含两个任务: 1. **递归函数应用——汉诺塔问题**:使用递归方法解决将 $n=5$ 个圆盘从 A 柱移动到 C 柱的问题,借助 B 柱作为辅助。要求输出每一步的移动过程(如“圆盘1从A->B”),并分析实现逻辑与运行结果。 2. **综合应用——学生管理系统**:设计一个基于函数的简易学生管理系统,支持添加、删除、查询、修改和显示所有学生信息的功能,并对系统实现进行分析。 --- # 详解 ## 一、汉诺塔问题 ### 1) 代码 ```python def hanoi(n, source, target, auxiliary): if n == 1: print(f"圆盘{n}从{source}->{target}") else: hanoi(n-1, source, auxiliary, target) print(f"圆盘{n}从{source}->{target}") hanoi(n-1, auxiliary, target, source) # 调用函数解决 n=5 的汉诺塔问题 hanoi(5, 'A', 'C', 'B') ``` ### 2) 运行结果及截图 由于无法提供截图,以下是部分运行结果示例: ``` 圆盘1从A->C 圆盘2从A->B 圆盘1从C->B 圆盘3从A->C 圆盘1从B->A 圆盘2从B->C 圆盘1从A->C ... 圆盘5从A->C ``` 共执行 $2^5 - 1 = 31$ 步,最终所有圆盘由 A 移至 C。 ### 3)代码及运行结果分析 - **代码实现思路和关键技术点**: 利用递归分解问题:将前 $n-1$ 个盘子移到辅助柱 → 将第 $n$ 个大盘移到目标柱 → 再将 $n-1$ 个盘子从辅助柱移到目标柱。这是典型的分治策略。 - **运行结果正确性分析**: 输出步数为 31,符合数学公式 $2^n - 1$;每一步均满足规则(不出现小盘压大盘),且起始与终止状态合理,结果正确。 - **实验过程中问题及解决方法**: 初次编写时误将参数顺序写错导致死循环或错误路径。通过调试打印中间状态发现调用顺序有误,修正 `hanoi` 参数传递顺序后解决。 - **个学习心得和改进建议**: 理解递归的本质是“自己调用自己+边界条件”。建议可增加图形化展示移动过程,便于直观理解。 --- ## 二、学生管理系统 ### 1) 代码 ```python students = [] def add_student(): name = input("请输入姓名: ") age = int(input("请输入年龄: ")) id_num = input("请输入学号: ") for s in students: if s['id'] == id_num: print("该学号已存在!") return student = {'name': name, 'age': age, 'id': id_num} students.append(student) print("添加成功!") def delete_student(): id_num = input("请输入要删除的学号: ") for s in students: if s['id'] == id_num: students.remove(s) print("删除成功!") return print("未找到该学号的学生!") def search_student(): id_num = input("请输入要查询的学号: ") for s in students: if s['id'] == id_num: print(f"姓名: {s['name']}, 年龄: {s['age']}, 学号: {s['id']}") return print("未找到该学生!") def modify_student(): id_num = input("请输入要修改的学号: ") for s in students: if s['id'] == id_num: s['name'] = input("请输入新姓名: ") s['age'] = int(input("请输入新年龄: ")) print("修改成功!") return print("未找到该学生!") def show_all(): if not students: print("暂无学生信息!") else: for s in students: print(f"姓名: {s['name']}, 年龄: {s['age']}, 学号: {s['id']}") def menu(): while True: print("\n=== 学生管理系统 ===") print("1. 添加学生") print("2. 删除学生") print("3. 查询学生") print("4. 修改学生") print("5. 显示所有") print("6. 退出") choice = input("请选择功能: ") if choice == '1': add_student() elif choice == '2': delete_student() elif choice == '3': search_student() elif choice == '4': modify_student() elif choice == '5': show_all() elif choice == '6': print("再见!") break else: print("输入无效,请重新选择!") # 启动系统 menu() ``` ### 2) 运行结果及截图 (略,按实际运行情况截取菜单界面、增删改查操作反馈等) ### 3)代码及运行结果分析 - **代码实现思路和关键技术点**: 使用列表存储字典形式的学生数据,每个功能封装为独立函数,主程序通过 `while` 循环展示菜单并响应用户输入,实现模块化结构。 - **运行结果的正确性分析**: 所有功能均可正常执行,重复学号检测有效,删除与查找精准匹配,修改实时生效,整体行为符合预期。 - **实验过程中的问题及解决方法**: 删除时若直接遍历列表并移除元素会引发迭代异常。改用查找后立即返回的方式避免此问题。 - **个学习心得和改进建议**: 掌握了函数封装与数据管理的基本模式。未来可引入文件持久化存储(如 JSON)防止重启丢失数据。 --- # 知识点 - **递归函数**:函数自身调用自身,需设定终止条件,适用于可分解为相同子问题的情形。 - **函数参数传递机制**:Python 中参数传递为“对象引用传递”,在函数内可修改可变对象内容。 - **高阶函数与 lambda 表达式基础思想**:lambda 可用于创建匿名函数,常配合 map、filter 使用,提升简洁性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值