递归的理解、内存占用以及使用场景

递归的理解

 递归是一种在函数或算法中调用自身的编程技巧。在递归中,问题被分解为更小的子问题,每个子问题都是原始问题的规模更小的版本,直到达到基本情况(终止条件),然后逐层返回解决方案,最终得到原始问题的解。

递归的两个关键元素

基本情况(终止条件):递归函数必须定义一个或多个基本情况,当满足这些条件时,递归将停止。这是为了避免无限递归,确保递归过程能够终止。

递归调用:递归函数在解决问题时会调用自身,但是每次调用时问题的规模都会减小,逐渐接近基本情况。通过递归调用,问题会被分解为更小的子问题,直到达到基本情况为止。

递归的优势

可以通过简洁的方式解决某些复杂的问题,尤其是涉及到具有递归结构的数据或问题。递归可以使代码更加清晰、易读,并且能够直接基于问题的定义来解决问题。 

递归产生的问题

 可能导致性能问题和堆栈溢出。递归调用会占用额外的内存空间,而且如果递归深度过大,可能会导致堆栈溢出。因此,在使用递归时,需要确保递归的停止条件能够被满足,并且递归的深度不会过大。

递归内存占用演示

 简单写一个递归:不满足if中的条件的时候跳出。

function fn (i) {
    if (i < 10) {
        i ++;
        fn(i);
        console.log(i);
    }
}
fn(0) // 10,9,8,7,6,5,4,3,2,1

上述代码打印的结果是:10 9 8 7 6 5 4 3 2 1;为什么是倒序输出结果,这里需要结合函数在栈内存(先进后出)中的存储加以演示。

图中每次递归会产生一个新的栈内存,直至达到终止条件执行完整个递归,根据黑色箭头的顺序,从后向前释放内存,最后一个内存先释放,然后依次执行完前面的函数并释放该函数所在内存。

假如递归没有写出口

无限递归:递归函数会无限地调用自身,不会停止。这会导致程序陷入死循环,不断消耗计算资源,最终可能导致栈溢出或程序崩溃。

内存耗尽:每次递归调用都会在内存中创建一个函数执行上下文,如果递归没有终止条件,将会无限地创建新的函数执行上下文,占用大量的内存空间。这可能导致内存耗尽,程序因为无法分配足够的内存而崩溃。

运行时间过长:无限递归会导致程序陷入无限循环,无法得到结果。这会导致程序运行时间非常长,甚至无法正常结束。在实际应用中,这是不可接受的,因为程序需要及时响应和返回结果。

递归必须写出口!!!

递归适用的场景

递归通常适用于解决具有递归结构的问题,即问题可以被自身的子问题所定义或划分。

例如,树的遍历、图的搜索、排列组合等问题常常可以使用递归来实现。

// 递归遍历树
function traverseElTree(node) {
  if (!node) {
    return;
  }
  
  // 处理当前节点
  console.log(node.label); // 假设节点有一个 label 属性表示节点的标签文本
  
  // 递归遍历子节点
  if (node.children && node.children.length > 0) {
    node.children.forEach(child => {
      traverseElTree(child);
    });
  }
}

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值