【发布时间】:2013-09-21 12:01:06
【问题描述】:
我在 C# 中实现了一个四叉树,并且遇到了一个奇怪的情况,即递归似乎比迭代执行得更好,尽管看起来应该相反。
我的节点如下所示:
class QuadNode
{
private QuadNode topLeft;
private QuadNode topRight;
private QuadNode bottomRight;
private QuadNode bottomLeft;
// other fields...
}
为了遍历树,我使用了以下递归方法,我在根节点上调用它:
Traverse()
{
// visit 'this'
if (topLeft != null)
topLeft.Traverse();
if (topRight != null)
topRight.Traverse();
if (bottomRight != null)
bottomRight.Traverse();
if (bottomLeft != null)
bottomLeft.Traverse();
}
主要是出于兴趣,我尝试创建一种遍历树的迭代方法。
我向每个节点添加了以下字段:private QuadNode next,当我创建树时,我使用队列执行广度优先遍历,将每个节点的 next 字段链接到行中的下一个节点。本质上,我从树的节点创建了一个单链表。
此时我可以使用以下方法遍历树:
Traverse()
{
QuadNode node = this;
while (node != null)
{
// visit node
node = node.next;
}
}
在测试了每种方法的性能后,我很惊讶地发现迭代版本始终比递归版本慢得多。我已经在大树和小树上进行了测试,递归方法总是更快。 (我使用 aStopwatch 进行基准测试)
我已经确认这两种方法都成功遍历了整个树,并且迭代版本只按计划访问每个节点一次,所以它不是它们之间的链接有问题。
在我看来,迭代版本的性能似乎很明显......这可能是什么原因?我是否忽略了为什么递归版本更快的一些明显原因?
我正在使用 Visual Studio 2012 并在 Release 下编译,任何 CPU(首选 32 位未选中)。
编辑:
我打开了一个新项目并创建了一个简单的测试,它也证实了我的结果。
以下是完整代码:http://pastebin.com/SwAsTMjQ
代码没有注释,但我认为它是非常自我记录的。
【问题讨论】:
-
您的测量结果在哪里?
-
@Arie 他所看到的完全相反,因此他提出了问题。在他的情况下,迭代较慢。
-
如何存储“下一个”指针?您是否将您的代码更改为在更改为下一个时仅存储一个节点指针?
-
你为什么不采用与递归相同的方法(深度优先)并在接下来访问一堆元素?计时时,有多少额外的时间用于创建链表?
标签: c# performance recursion iteration complexity-theory