我不确定以下代码如何显示rChild和lChild中的数据。在到达显示代码之前,调用该函数并传递参数ptr-rChild。因此,显示代码永远不会有机会执行,因为在显示代码之前总是有一个函数调用。此外,当再次调用该函数时,但这次参数是lChild,当第一次使用参数rChild进行函数调用时,它如何在lChild中显示数据。
void CTree::DisplayTree(PersonRec * ptr)
{
if (ptr != NULL)
{
DisplayTree(ptr->rChild);
cout << "Name: " << ptr->name << "\t" << "Bribe Offered: " << ptr->bribe << endl;
DisplayTree(ptr->lChild);
}
}
答案 0 :(得分:2)
以下面的树为例,其中Node0
是传递给PersonRec*
的第一个DisplayTree
(右侧是访问节点以供参考的顺序):
Node0 1st
/ \ / \
Node2 Node1 5th 2nd
/ | | \ / | | \
NULL NULL NULL NULL 7th 6th 4th 3rd
Node1
传递给DisplayTree
(作为rChild
)NULL
传递给DisplayTree
(作为rChild
)NULL
并返回第二个调用(Node1
)Node1
,然后将NULL
传递给DisplayTree
(作为lChild
)Node1
)Node0
)Node0
,然后将Node2
传递给DisplayTree
(作为lChild
)NULL
传递给DisplayTree
(作为rChild
)Node2
)Node2
,然后将NULL
传递给DisplayTree
(作为lChild
)Node2
)修改:使用较小的示例来处理您的评论。考虑一个只有一个节点没有子节点的树,这次让我们更多地关注代码。树看起来像这样:
Node0
/ \
NULL NULL
第一次调用代码时,会传入Node0
。if (ptr != NULL)
为true
,因此执行会输入if语句。下一行DisplayTree(ptr->rChild);
使用NULL
调用该函数。在该调用期间,if (ptr != NULL)
为false
,因此执行不会进入if语句。结果,执行返回到上一个调用,下一行代码是cout << "Name: " << ptr->name...
,它打印Node0
的信息,这就是输出的原因。该行之后的调用DisplayTree(ptr->lChild);
也无效,因为它传递了NULL
,然后所有递归都已完成
答案 1 :(得分:0)
答案 2 :(得分:0)
&#39;递归函数的概念&#39;很简单,但在第一次遇到它时可能有点吓人。有很多很好的资源,我个人非常喜欢以下几个:
http://www.cplusplus.com/articles/D2N36Up4/
http://www.cprogramming.com/tutorial/lesson16.html
正如您所知,函数调用放在堆栈内存中,由于此内存有限,一旦调用太多而没有结束,程序将崩溃。因此,递归定义的一个重要部分是停止标准,它指定何时以及在什么情况下,函数将停止调用自身并打破递归循环。在您的代码中,行if (ptr != NULL)
是停止条件。因此,你的问题的答案
所以显示代码永远不会有机会执行,因为在显示代码之前总是有一个函数调用。
是DisplayTree
的递归调用将在到达rChild
和lChild
为NULL
的树的叶子时结束。也就是说,DisplayTree(ptr->rChild);
将立即为叶节点返回,cout << "Name: " << ptr->name << "\t" << "Bribe Offered: " << ptr->bribe << endl;
代码行有机会执行并打印数据。当然,这完全取决于你的树是否定义明确。从您的代码可以假设该函数期望叶节点具有rChild和lChild的NULL值。因此,如果树是按照此规范构造的,则将满足停止条件并显示数据。另一方面,如果树构造不正确,程序将因堆栈溢出而崩溃(请参阅en.wikipedia.org/wiki/Stack_overflow)
答案 3 :(得分:0)
每当看到递归函数调用时,都知道函数将在某个时刻返回,并且将执行下一个语句。但是怎么样?好吧,DisplayTree(ptr->rChild)
将继续调用自身,并在收到空指针时停止。这就是为什么你的if (ptr != NULL)
检查如此重要 - 它可以防止无限递归,而且逻辑上你也不想取消引用空指针。
当接收到空指针的函数返回时,编译器将调用堆栈下移到进行调用的最后一帧。在那里它将继续下一个声明。这将是它将在树中打印最右边的节点。然后它将以ptr->lChild
递归调用自身,它将在 树中找到最右边的节点,然后重新开始该过程。
这是一个inorder遍历的示例。当我看到这样的函数时,我想对自己说&#34;这个函数首先为右子树,当前节点,然后是它的左子树&#34;执行中间语句。这让它变得更加易于理解。