当前位置: 首页 > 知识库问答 >
问题:

了解递归函数的工作原理

麻超
2023-03-14

正如标题所解释的,我有一个非常基本的编程问题,但我还没有找到。过滤掉所有(非常聪明的)“为了理解递归,你必须首先理解递归。”各种在线线程的回复我仍然不太明白。

当我们面对不知道自己不知道的事情时,我们可能会提出错误的问题或错误地提出正确的问题。我将分享我的“想法”。我的问题是希望有类似观点的人能够分享一些知识,帮助我打开递归灯泡!

以下是html" target="_blank">函数(语法用Swift编写):

func sumInts(a: Int, b: Int) -> Int {
    if (a > b) {
        return 0
    } else {
        return a + sumInts(a: a + 1, b: b)
    }
}

我们将使用2和5作为参数:

println(sumInts(a: 2, b: 5))

显然答案是14。但是我不清楚这个值是如何实现的。

这是我的两个难题:

>

  • 递归调用该函数,直到满足条件为止。这种情况是一种

    在每次迭代中打印出“a”的值会产生一个我期望的值:2,3,4,5(此时5.1

    我的第一个想法是,类似以下的事情正在神奇地发生:

    var answer = a;
    answer += a+1 until a > b;
    return answer;   
    

    所以排除魔法,我只是没有得到什么。我想了解正在发生的事情,而不仅仅是隐含的。

    如果有人能善意地解释一下在这种函数中技术上发生了什么,为什么结果不是0,以及最终如何将一个sumits(a:a 1,b:b)=14,我将永远欠你的债。

  • 共有3个答案

    邢宏浚
    2023-03-14

    要理解递归,你必须以不同的方式思考问题。不是一个整体上有意义的大逻辑步骤序列,而是一个大问题,分解成更小的问题并解决这些问题,一旦你对子问题有了答案,你就结合子问题的结果来解决更大的问题。想想你和你的朋友需要在一个大桶里数弹珠的数量。你们每个人都拿一个更小的桶,然后单独去数,当你完成时,你把总数加在一起...现在,如果你们每个人都找到一些朋友,把桶进一步分开,那么你只需要等其他朋友算出他们的总数,把它拿回来给你们每个人,你把它加起来。以此类推。特殊情况是,当你只有1个大理石要数,然后你把它退回来,说1。让你上面的其他人做加法,你完成了。

    您必须记住,每次函数递归调用自己时,它都会创建一个包含问题子集的新上下文,一旦该部分得到解决,它就会返回,以便完成上一次迭代。

    让我向您展示步骤:

    sumInts(a: 2, b: 5) will return: 2 + sumInts(a: 3, b: 5)
    sumInts(a: 3, b: 5) will return: 3 + sumInts(a: 4, b: 5)
    sumInts(a: 4, b: 5) will return: 4 + sumInts(a: 5, b: 5)
    sumInts(a: 5, b: 5) will return: 5 + sumInts(a: 6, b: 5)
    sumInts(a: 6, b: 5) will return: 0
    

    一旦执行了sumInts(a:6,b:5),就可以计算结果,因此可以使用得到的结果返回链:

     sumInts(a: 6, b: 5) = 0
     sumInts(a: 5, b: 5) = 5 + 0 = 5
     sumInts(a: 4, b: 5) = 4 + 5 = 9
     sumInts(a: 3, b: 5) = 3 + 9 = 12
     sumInts(a: 2, b: 5) = 2 + 12 = 14.
    

    表示递归结构的另一种方法:

     sumInts(a: 2, b: 5) = 2 + sumInts(a: 3, b: 5)
     sumInts(a: 2, b: 5) = 2 + 3 + sumInts(a: 4, b: 5)  
     sumInts(a: 2, b: 5) = 2 + 3 + 4 + sumInts(a: 5, b: 5)  
     sumInts(a: 2, b: 5) = 2 + 3 + 4 + 5 + sumInts(a: 6, b: 5)
     sumInts(a: 2, b: 5) = 2 + 3 + 4 + 5 + 0
     sumInts(a: 2, b: 5) = 14 
    
    艾修筠
    2023-03-14

    我认为这种混乱源于将其视为多次调用的“同一个函数”。如果你把它想象成“同一个函数的许多副本被调用”,那么可能会更清楚:

    只有一个函数的副本返回0,并且它不是第一个(它是最后一个)。所以调用第一个的结果不是0。

    对于第二点困惑,我认为用英语拼写递归会更容易。阅读这一行:

    return a + sumInts(a + 1, b: b)
    

    as“return the value of‘a’plus(函数的另一个副本的返回值,即‘a’plus的副本值)(函数的另一个副本的返回值,即‘a’plus的第二个副本值(…)”,随着函数的每个副本生成自身的新副本,a增加1,直到a

    当你到达a时

    (编辑:另外,需要注意的是,我提到的函数的副本堆栈是一个占用真实内存的真实事物,如果它变得太大,会使您的程序崩溃。编译器在某些情况下可以优化它,但是耗尽堆栈空间是许多语言中递归函数的一个重大而不幸的限制)

    公德明
    2023-03-14

    递归调用函数,直到满足条件。这种情况是

    以下是计算机计算sumInts(2,5)如果能够:

    I want to compute sumInts(2, 5)
    for this, I need to compute sumInts(3, 5)
    and add 2 to the result.
      I want to compute sumInts(3, 5)
      for this, I need to compute sumInts(4, 5)
      and add 3 to the result.
        I want to compute sumInts(4, 5)
        for this, I need to compute sumInts(5, 5)
        and add 4 to the result.
          I want to compute sumInts(5, 5)
          for this, I need to compute sumInts(6, 5)
          and add 5 to the result.
            I want to compute sumInts(6, 5)
            since 6 > 5, this is zero.
          The computation yielded 0, therefore I shall return 5 = 5 + 0.
        The computation yielded 5, therefore I shall return 9 = 4 + 5.
      The computation yielded 9, therefore I shall return 12 = 3 + 9.
    The computation yielded 12, therefore I shall return 14 = 2 + 12.
    

    如你所见,一些对函数sumits的调用实际上返回0,但这不是最终值,因为计算机仍然需要在0上加5,然后在结果上加4,然后加3,然后加2,正如我们计算机思想的最后四句所描述的那样。注意,在递归中,计算机不仅必须计算递归调用,还必须记住如何处理递归调用返回的值。计算机内存中有一个特殊的区域叫做堆栈,在那里保存此类信息,这个空间是有限的,过于递归的函数可能会耗尽堆栈:这是堆栈溢出,为我们最喜欢的网站命名。

    你的陈述似乎隐含了这样一个假设,即计算机在进行递归调用时忘记了它所处的位置,但事实并非如此,这就是为什么你的结论与你的观察结果不匹配。

    2.在每次迭代中打印出“a”的值会产生一个我期望的值:2、3、4、5(此时5 1

    这是因为返回值不是a本身,而是a的值和递归调用返回的值的总和。

     类似资料:
    • 我试图使一个函数,如果收到的数字是一个有效的增值税号码,返回true,否则False。 为了使数字有效,算法是: 设s为第8位数字乘以2,第7位数字乘以3,第6位数字乘以4,第5位数字乘以5,第4位数字乘以6,第3位数字乘以7,第2位数字乘以8,第1位数字乘以9的乘积之和。设r为s除以11的整数的余数。否则,最后一位数字必须从r中减去11 所以我做了这个函数: 但是当我运行它应该返回 时,但该函数

    • 问题内容: 我正在尝试使用递归调用从redis中获取数据,并在成员返回null时停止并返回。 所以我的数据是这样添加的: 最终数据应如下所示: 这是我正在弄乱的代码(从不同来源将它们拼凑在一起),但是我不知道自己在做什么。不知道这段代码是否有用,我可能会偏离正轨。 我可以看一下示例,从理论上看它应该如何工作,但是我无法确定它如何与q实现一起工作。任何帮助将不胜感激。 问题答案: 兑现承诺时,尽量做

    • 我正在尝试在XSLT 2.0中编写一个尾递归函数,它遍历日期的多值变量并返回最早的一个。出于某种原因,我的函数未被SaxonHE9.4识别为尾递归,当输入文件有超过150-200个条目左右时,我会收到以下错误: tail\u rec\u测试第73行出错。xsl:嵌套函数调用太多。可能是由于无限递归。内置模板规则 以下是我的xml输入: 这就是我的xsl-file的样子: 如何将其转换为正确的尾部递

    • 此指令可与锁前缀一起使用,以允许指令原子执行。为了简化与处理器总线的接口,目的操作数接收一个写周期,而不考虑比较的结果。如果比较失败,则写回目标操作数;否则,将源操作数写入目标。 我很难理解最后一句(但可能也很难理解整个图表) 写回什么? 源操作数是什么?是吗?据我所知,这个CAS指令只接受一个操作数(内存目标)。 如果有人能重新措辞和/或解释关于无条件写入的这一点,我将不胜感激。

    • Python/CS新手,试图了解特定递归函数如何“在引擎盖下”工作,函数的堆栈框架如何运行,它们“持有”的值是什么 我知道这里有很多关于递归函数的文章/帖子,这里有它们如何工作的示例,但递归的概念和堆栈如何工作/它们在递归函数中的作用有点棘手,我找不到任何清晰简洁的解释。 假设我们有以下递归函数来反转字符串中的字符: 其输出为:< code>olleh 我认为<code>reverse_strin

    • 问题内容: 我得到以下代码: 我可以理解诸如阶乘和斐波那契这样的递归,但是对于这一点我不能理解。我试图追踪逻辑: 我总是以其他任何数字结尾7,我知道这是错误的,因为在运行程序时会得到不同的值。您能帮我了解递归在这里如何工作吗? 问题答案: 我认为这是不言自明的,如果您需要更多信息,请评论!