我很难找到递归的工作方式。一些教科书 说“递归就是一个函数一次又一次地调用自己 直到满足一些基本条件“。
有些书说“递归就是一个函数调用另一个函数的时候 一次又一次地运作直到满足一些基本条件“。
这是真的吗?如果两者都是真的,我们可以考虑下面给出的例子 作为一个递归?如果否,那么在性能方面哪个更好,
下面的代码或递归?
def Function1()
{
/* do something */
}
def Function2()
{
for(i=0; i<=10; i++)
{
call Function1()
}
}
答案 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);
}
请查看以下网址,了解效果标准。
答案 2 :(得分:1)
让我把各个部分放在一起:你提供的代码可能是递归的,也可能不是。这取决于 Function1 是否调用 Function2 这一事实。如果是这种情况,那么你会有一个互斥的递归,正如EOF所指出的那样。
但是,这种情况不会像正常递归那样频繁发生(纯功能环境除外)。正常的递归只包含一个调用本身的函数(另一个函数的insteaf)。
进一步解释和介绍如何,例如例如,递归阶乘有效,见here。
答案 3 :(得分:1)
递归就是
控制流程从一个函数传递到同一个函数(直接或间接),而不先返回。
在您的示例中,Function1
从Function2
重复调用,但会在再次调用之前从每次调用返回,因此不会以递归方式调用它。
答案 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)
当根据自身或其自身定义事物时发生递归 类型。递归用于各种学科 语言学到逻辑学。最常见的递归应用是 数学和计算机科学,其中定义的函数是 在自己的定义中应用。虽然这显然定义了一个 无限数量的实例(函数值),通常是在 这样一种方式就是不会出现循环或无限的引用链。
所以,如果你有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
。当某些东西是它自己的依赖项时发生递归,而你的代码有一个依赖于另一个函数的函数。关于性能的问题几乎无法回答,因为有无限的方法来实现有或没有递归的事物,当你将递归方法与非递归方法进行比较时,你需要具体实现,或者至少非常关于如何实施这两个案件的严格意见。但是,一般来说,最好选择非递归方法,因为递归方法通常会对内存的堆栈部分产生问题,包括堆栈溢出或无限函数调用以及由于错误导致的崩溃。