这段代码可以称为递归。如果没有,哪个更有优势,给出下面的代码或递归?

时间:2017-06-24 11:06:27

标签: c function recursion

  1. 我很难找到递归的工作方式。一些教科书 说“递归就是一个函数一次又一次地调用自己 直到满足一些基本条件“。

  2. 有些书说“递归就是一个函数调用另一个函数的时候     一次又一次地运作直到满足一些基本条件“。

  3. 这是真的吗?如果两者都是真的,我们可以考虑下面给出的例子     作为一个递归?如果否,那么在性能方面哪个更好,

    下面的代码或递归?

  4.     def Function1()
        {
            /* do something */
        }
    
        def Function2()
        {
            for(i=0; i<=10; i++)
            {
                 call Function1()
            }
        }
    

6 个答案:

答案 0 :(得分:5)

实际上,代码显示了对handleMissingPage()的迭代调用,如果在$slug = '/'; if(strlen($path) > 1) $slug = ltrim($path, '/'); if ($page = Page::where('path', $slug)->first()) return response() ->view($page->template, ['pageBuilder' => $page], 200); abort(404); 的主体内有Function1()的调用,那么它将是一个间接递归 - 一个函数调用第二个函数,然后再次调用第一个函数。

通常,递归函数直接或间接调用自身。在直接递归函数中,Function1()再次调用自身。在间接递归中,函数Function2()调用函数foo(),后者又调用函数foo(),直到达到基本情况。 (然后,最终结果以与初始递归函数调用完全相反的顺序累加。)

现在,回答你的问题:

  

此代码可以称为递归。如果没有,哪个更有优势,给出下面的代码或递归?

没有。迭代缺少多个激活记录(或stack frames),这使其成为更好的替代方案。

答案 1 :(得分:3)

应根据要求使用递归,并且当您知道基本条件并且不知道应该调用循环的次数时。 递归可以是不同的类型,例如可以有正常的递归,无限递归,间接递归等。 正常递归意味着在满足基本条件之前调用相同的函数 无限递归是没有任何基本条件的地方。 间接递归就像呼叫b和b呼叫c而c呼叫回叫a&#39; a&#39;被间接称为

基本递归示例:

foo() 
{
    base_condition;
        return;
    foo();
}
main()
{
    foo();
}

您的示例基本条件可以是变量等于运行10次。

fun(int x)
{
    if(x == 0)
        return;
    fun(--x);
}
main
{
    fun(10);
}

请查看以下网址,了解效果标准。

performance between looping and recursion

答案 2 :(得分:1)

让我把各个部分放在一起:你提供的代码可能是递归的,也可能不是。这取决于 Function1 是否调用 Function2 这一事实。如果是这种情况,那么你会有一个互斥的递归,正如EOF所指出的那样。

但是,这种情况不会像正常递归那样频繁发生(纯功能环境除外)。正常的递归只包含一个调用本身的函数(另一个函数的insteaf)。

进一步解释和介绍如何,例如例如,递归阶乘有效,见here

答案 3 :(得分:1)

递归就是

  

控制流程从一个函数传递到同一个函数(直接或间接),而不先返回。

在您的示例中,Function1Function2重复调用,但会在再次调用之前从每次调用返回,因此不会以递归方式调用它。

答案 4 :(得分:0)

递归是指函数直接或间接调用自身。

通常在类C语言中,只有当数据类似于树时才使用递归。例如,您有一个由节点组成的树,其中包含&#34; next&#34;成员表示兄弟姐妹和孩子&#34;指示子项的成员(可能是XML文件或目录树)。你想要节点的数量

int getNodes(Node root)
{
    int answer = 1;
    for(sib = root.next; sib != null; sib = sib.next)
    {
       answer += 1;
       if(sib.child != null)
          answer += getNnodes(sib.child);
    }
    if(node.child != null)
       answer += getNodes(node.child);
    return answer;
}

如果root == null,你可以通过返回0使代码更整洁但效率更低。

但是,您可以使用递归进行迭代。可以把它想象成送给街道的信件。你可以沿着街道去掉你口袋里的字母(迭代)。或者您可以将信件发送到街道的第一个房子,宣布街道为一个房子更短,然后重复直到街道消失(递归)。后者看起来很古怪,但它对于自动检查算法的正确性有一些优势。例如,如果你忘记增加它,就不会陷入无限循环。

答案 5 :(得分:0)

  

当根据自身或其自身定义事物时发生递归   类型。递归用于各种学科   语言学到逻辑学。最常见的递归应用是   数学和计算机科学,其中定义的函数是   在自己的定义中应用。虽然这显然定义了一个   无限数量的实例(函数值),通常是在   这样一种方式就是不会出现循环或无限的引用链。

Source

所以,如果你有foo并且为了计算或执行foo,你需要至少再次重复foo,然后你有一个递归。例如:

<强> N! = 1 * 2 * 3 * ... * n

这是一个迭代定义:

int fact(n) {
    int ret = 1;
    int i = 1;
    while (++i < n) ret *= i;
    return ret;
}

这是一个递归定义:

int fact(n) {
    return (n == 1) ? 1 : (n * fact(n - 1));
}

由于您的代码使用Function2的多个用法计算Function1,因此它不是递归的,因为您无需调用Function2来评估Function 2,您也不需要致电Function1来评估Function1。当某些东西是它自己的依赖项时发生递归,而你的代码有一个依赖于另一个函数的函数。关于性能的问题几乎无法回答,因为有无限的方法来实现有或没有递归的事物,当你将递归方法与非递归方法进行比较时,你需要具体实现,或者至少非常关于如何实施这两个案件的严格意见。但是,一般来说,最好选择非递归方法,因为递归方法通常会对内存的堆栈部分产生问题,包括堆栈溢出或无限函数调用以及由于错误导致的崩溃。