【递归】:原理、应用与案例解析 ,助你深入理解递归核心思想

本文探讨了递归在计算机科学中的概念、优点和缺点,涉及递归的基本情况、递归情况、常见应用场景如树遍历、分治算法等。同时指出了递归可能导致的性能损耗和内存消耗问题,以及如何通过控制递归深度、优化算法和尾调用来避免栈溢出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

递归

1.基础简介

递归在计算机科学中,递归是一种解决计算问题的方法,其中解决方案取决于同一类问题的更小子集

例如 递归遍历环形链表

  • 基本情况(Base Case):基本情况是递归函数中最简单的情况,它们通常是递归终止的条件。在基本情况下,递归函数会返回一个明确的值,而不再进行递归调用。
  • 递归情况(Recursive Case):递归情况是递归函数中描述问题规模较大的情况。在递归情况下,函数会调用自身来解决规模更小的子问题,直到达到基本情况。

优点

  1. 简洁清晰:递归能够将复杂的问题简化成更小的子问题,使得代码更加清晰易懂。
  2. 问题建模:递归能够自然地将问题建模成递归结构,使得问题的解决变得更加直观。
  3. 提高代码复用性:通过递归,可以在不同的情景中复用相同的解决方案。

缺点

  1. 性能损耗:递归调用涉及函数的重复调用和堆栈的频繁使用,可能会导致性能下降。
  2. 内存消耗:每次递归调用都需要在堆栈中存储函数的调用信息,可能会导致堆栈溢出的问题。
  3. 难以理解和调试:复杂的递归调用可能会导致代码的难以理解和调试,特别是递归函数中存在多个递归调用时。

常用场景

  1. 树和图的遍历:树和图的结构天然适合递归的处理方式,如深度优先搜索(DFS)。
  2. 分治算法:许多分治算法,如归并排序和快速排序,都是通过递归实现的。
  3. 动态规划:动态规划问题中,递归可以帮助描述问题的递归结构,但通常需要使用记忆化搜索或者自底向上的迭代方式来提高性能。
  4. 排列组合问题:许多排列组合问题,如子集、组合、排列等,可以通过递归实现。
/**
 * 递归进行遍历
 * @param node   下一个节点
 * @param before 遍历前执行的方法
 * @param after  遍历后执行的方法
 * @deprecated  递归遍历,不建议使用,递归深度过大会导致栈溢出。建议使用迭代器,或者循环遍历,或者使用尾递归,或者使用栈
 * @see #loop(Consumer, Consumer)
 */
public void recursion(Node node, Consumer<Integer> before, Consumer<Integer> after){
   
    // 表示链表没有节点了,那么就退出(注意 环形链表的 末尾 不是null 而是头节点)
    if (node == sentinel){
   
        return;
    }
    // 反转位置就是逆序了
    before.accept(node.value);
    recursion(node.next, before, after);
    after.accept(node.value);
}
  1. 自己调用自己,说明每一个函数对应着一种解决方案,自己调用自己意味着解决方案是一样的或者说是有规律的
  2. 每次调用,函数处理的数据相对于上一次会缩减,而且最后会缩减至无需继续递归
  3. 内层函数调用(子集处理完成),外层函数才能调用完成

1.1.思路

首先需要确定自己的问题,能不能用递归的思路去解决

然后需要推导出递归的关系,父问题和子问题之间的关系, 以及递归的中止条件

f ( n ) = { 停止 , n = n u l l f ( n , n e x t ) , n ≠ n u l l f(n) = \begin{cases} 停止&, n = null \\ f(n,next)&, n \neq null \\ \end{cases} f(n)={ 停止f(n,next),n=null,n=null

  1. 深入到最里层的 叫做递
  2. 从最里层出来的叫做归
  3. 在递过程中,外层函数内的局部变量(以及参数方法)并未消失,归的时刻还会用到。

2.案例

2.1.案例1-求阶乘

@Test
@DisplayName("测试-递归-阶乘")
public void test1(){
   
    int factorial = factorial(5);
    logger.error("factorial :{}",factorial);
}


/**
 * 阶乘
 * @param value 阶乘的值
 * @return 阶乘的结果
 */
public int factorial(int value){
   
    // 递归的终止条件
    if
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值