今天我在php中使用递归制作了一个方法并对它感兴趣。什么问题实际上可以递归解决?对于我们可以使用递归的东西?
我开始在网上搜索并搜索和搜索,但我找不到任何东西。
所以我在问,我怎样才能使用递归?
有一些限制吗?我们不能用递归但用标准循环做的事情吗?我想知道我是否可以在我的代码中正常使用现在的递归。
答案 0 :(得分:4)
使用递归我们能做些什么?
解决递归问题。父子问题,每个孩子都可以再次成为父母,这是最常见的问题。
HasAttachment
是否有一些限制?
是。 PHP(和其他编程语言)跟踪哪些代码调用哪个函数,因此它知道函数返回后的继续。这称为function doSomethingWithNode($node)
{
// Do something with $node
// Loop over all childs, and run this code for those childs too, and for those childs, and for those childs, and ...
foreach($node->getChilds() as $child) {
doSomethingWithNode($child);
}
}
doSomethingWithNode($rootNode);
。向call stack
添加新条目将花费一些内存和一些时间。当你有很多(数百万)次迭代时,主要是第一个CAN导致问题。
根据您的安装,call stack
甚至可能会受到限制。默认情况下它不是。通过安装call stack
- 扩展,它最多可以提供100个嵌套调用(默认情况下,可以在配置中更改)。在这些设置中,它将导致致命错误(example)。
我们可以通过标准循环来处理递归但我们能做什么?我想知道我是否可以在我的代码中正常使用现在的递归
由于上述限制,应谨慎使用递归。当您可以使用普通while或for循环解决它时:使用正常循环。大多数情况下,它将使代码更容易阅读。
当您关心可移植性时(例如编写开源项目时),您可能想要考虑xdebug用户。
答案 1 :(得分:3)
通过任何数据结构迭代的每种类型都可以通过递归来完成。实际上,您可以将for
,while
,do while
,foreach
等每个循环结构替换为简单的递归:
function factorial($n) {
$result = $n < 0 ? -1 : 1;
for($i = abs($n), $i > 1; $i--) {
$result *= $i;
}
return $result;
}
可写:
function factorial($n) {
$forHelper = function($result, $i) {
return $i === 1 ? $result : $forHelper($result * $i, $i - 1);
}
return $forHelper($n < 0 ? -1 : 1, abs($n));
}
这称为尾递归。在某些语言中,上面两个生成非常相似的运行时代码,但不是PHP。它为每次调用使用一些内存。对我来说,两者都具有相同的可读性,但我敢打赌,大多数程序员会发现循环更容易,特别是当它嵌套时。
使用递归而不是迭代,迭代图形或树的某些算法将具有更简单的版本:
function treeDepth($node) {
if( $node === null ) {
return 0;
} else {
return 1 + max(treeDepth($node->left), treeDepth($node->right));
}
}
这里的迭代解决方案需要某种方式来跟踪它需要访问的位置,因此您正在做一些由递归版本自动处理的内务处理。
function treeDepth($node) {
$max = 0;
$backtrack = [[0, $node]];
while( count($backtrack) ) {
list($depth, $node) = array_pop($backtrack);
while($node !== null) {
array_push($backtrack, [++$depth, $node->right]);
$node = $node->left;
}
$max = max($max, $depth);
}
return $max;
}
限制取决于语言。在PHP中,它为每个未分配给简单循环的调用帧分配一些内存。节点遍历始终使用内存,因为该进程本质上是递归的。
最终,您应该以尽可能清晰的方式编写代码,而不必考虑优化。使用最清晰的循环结构和最清晰的递归。只有当您真正遇到性能问题时,才应该分析和重写使用最多时间的部分。我用它来保留原始代码作为注释,如果它很短并记录在更复杂的迭代版本中实际发生的事情。在PHP中,函数调用本身很昂贵。