演示良好使用相互递归的示例

时间:2012-04-24 10:02:09

标签: algorithm recursion mutual-recursion

我想知道是否存在非人为的例子,其中相互递归是问题的最优雅解决方案,并且不能轻易地减少/内联到单个递归函数。 < / p>

我已经知道这个例子(来自Wikipedia

function even?(number : Integer)
    if number == 0 then
        return true
    else
        return odd?(abs(number)-1)

function odd?(number : Integer)
    if number == 0 then
        return false
   else
        return even?(abs(number)-1)

但严重的是,没有一个心智正常的人会以这种方式检查数字的平价。

我在这里查看了关于此主题的上一个答案 - Are there any example of Mutual recursion?,但没有一个答案是我正在寻找的。

我知道它在递归解析中很有用 - 可能是实现它的唯一逻辑方法,但我需要一个更清晰,更具体的例子(最好是数学例子)。

谢谢你的帮助?

修改

由于显然每个相互递归函数的元组都可以简化为单个函数,我宁愿知道是否存在使用相互递归函数最佳/最易读的情况方式。

4 个答案:

答案 0 :(得分:5)

用于绘制Sierpinski curve(以及其他一些曲线)的相互递归代码看起来相当优雅。

答案 1 :(得分:4)

我相信任何相互递归都可以很容易地简化为单个函数:

考虑两个函数f1和f2:

f1(p1, ..., pn) returns r1
f2(q1, ..., qm) returns r2

可统一为:

f12(which, p1, ..., pn, q1, ..., qn) returns (r1, r2)
    if which == 1
        <code of f1>
    else
        <code of f2>

这只是最糟糕的情况。通常一些参数或返回值应该相同。

答案 2 :(得分:1)

这取决于个人认为的个人敏感度&#34;优雅&#34;。但这是我的镜头。

Adam正在尝试安排为期6天的考试修订。每天他都会去:

  1. Rest(R)
  2. 学习数学(M)
  3. Study Computing(C)
  4. 亚当从未连续两天研究过两个不同的科目。亚当有多少种方式可以安排修改?

    解决方案:

    让我们使用符号s1 = "RMCRMM"来表示时间表。 s1不是有效的时间表,因为在时间表中的某一点,主题(M)后面紧跟着另一个主题(C)。有效时间表的一些示例包括:s2 = "MMRCCR"s3 = "MMRRRC"或甚至s4 = "RRRRRR"(祝s4好运!)。在每个时间表中,两个不同科目之间必须至少有一个休息日。

    我们可以使用相互递归来解决任务。让我们列举从1, 2, ..., 6开始的几天。让我们定义三个相互递归的函数R(k)M(k)C(k)。每个函数将计算部分时间表的数量,每个部分时间表的长度为k,其中最后几天分别为&#34; R&#34;,&#34; M&#34;和&#34; C&#34;。我们去(python):

    def R(k):
        if k == 1:
            return 1
        else:
            return R(k-1) + M(k-1) + C(k-1)
    
    def M(k):
        if k == 1:
            return 1
        else:
            return R(k-1) + M(k-1)
    
    def C(k):
        if k == 1:
            return 1
        else:
            return R(k-1) + C(k-1)
    

    然后我们可以通过评估R(6) + M(6) + C(6)

    来解决问题

    这样做的原因是因为我们计算了k天的(部分)时间表的可能方式,这可能以某种方式结束,而且唯一可能影响的方式我们选择如何到达那里是前一天发生的事情。通过这种方式,我们可以计算所有可能的时间表,并且我们只计算一次每个时间表。

    例如,对于我们完成的第3天,比如说&#34; C&#34;,&#34; XXC&#34;,我们可以达到这样的时间表的方式正是{{1因为我们可以来自一个时间表&#34; XCC&#34;或&#34; XRC&#34;,但不是&#34; XMC&#34;。

    显然,如果你想提高效率,你可能最终会使用memoisation / dynamic编程,但即便如此,相互递归可能是最易读/可理解的编码方式。问题

答案 3 :(得分:0)

如果你有适当的尾调用优化,你可以进行合作多任务处理:

f():
    do_something()
    g()

g():
    do_something_else()
    f()

如果碰巧在Scheme中编码,有时需要考虑这个问题。