我有一个关于return和递归函数的问题。
这也是基于我目前正在研究的二叉树。代码是
void Tree::display()
{
if( !root_ )
return;
display_r(root_);
}
void Tree::display_r(Tree *node)
{
if( 0 == node )
return;
display_r(node->left_);
std::cout << node->value_ << std::endl;
display_r(node->right_);
}这是正常工作的代码。编译并无故障运行,从最小到最大打印数字。然而,这并不是过去的情况。
上面的代码最初是用
return display_r(node->left_);
std::cout << node->value_ << std::endl;
return display_r(node->right_);但这并不管用。它只是返回而不打印任何内容。这是有道理的,返回不允许代码向下移动。
这就引出了一个有趣的问题。在编写树时,我经常想知道在递归函数中使用return是否是一个好地方。显然,只要return是在代码块中执行的最后一个命令,就可以使用。我认为甚至可以在display()函数中使用
void Tree::display()
{
if( !root_ )
return;
return display_r(root_);
}所以我的问题是:我什么时候确定我可以使用return,什么时候我不应该使用它?是否存在灰色地带,由我来决定什么是最好的,是否有安全网?例如,“当有疑问时,不要在递归函数中使用返回?”
谢谢!
发布于 2010-06-27 15:28:14
我建议更仔细地研究return关键字,并更多地练习递归。
return display_r(node->left_);
// this following code would not be executed in your example,
// you've already returned out of the function!
std::cout << node->value_ << std::endl;
return display_r(node->right_);这里的返回是必要的:
if( 0 == node )
return;..。因为这是递归算法的基本情况(也称为一般解决方案)。当您遇到子级的null时,您将停止,否则将继续。请注意,此代码是if语句的一部分。它只在某些情况下执行(正是在这种情况下,您希望过早地从函数中返回并停止递归)。
在您的特定情况下,您也可以完全不使用return来编写此代码,而且非常容易:
void Tree::display_r(Tree *node)
{
if (node) // equivalent to if (node != 0)
{
display_r(node->left_);
std::cout << node->value_ << std::endl;
display_r(node->right_);
}
}顺便说一句,没有冒犯的意思,看起来你似乎是在借用示例,而不是完全理解它们是如何工作的。试着自己想一想,试着去理解代码。如果需要,在每条指令旁边添加注释,以您可以理解的方式指示它做了什么。
还要尝试学习调试器;这一点我怎么强调都不为过。许多大学生在没有学习如何使用调试器的情况下完成了整个本科学位,这真是一种耻辱。这应该是最先学到的东西之一!使用调试器跟踪代码将真正帮助您了解您编写的代码的行为。如果你没有学到如何使用它,我建议你自己学习如何使用它。它将向你展示机器如何一步一步地检查你写的每一行代码。
发布于 2010-06-27 15:21:08
您只是使用您的返回,作为停止函数执行的一种方式。为什么不这样做呢?
void Tree::display_r(Tree *node)
{
if(node)
{
display_r(node->left_);
std::cout << node->value_ << std::endl;
display_r(node->right_);
}
}然后,如果没有节点,则不会执行任何操作。
您的所有函数都是void类型,这意味着它们应该不返回任何内容。基本上,您应该只使用return来停止函数。
这就是为什么你的返回值都不能像你想的那样工作,因为void函数根据定义返回void,换句话说,它们不能返回任何东西。
你可以返回it,或者指针,或者其他任何东西,但是你必须声明它,比如
int function() {
return 3;
}此外,当您调用具有返回的函数时,通常会将变量设置为等于这些返回的值。从上面开始:
x = function();切线
您可以在void函数中实际使用return语句来执行void函数。这通常不是一个好主意。下面是一个简单的例子:
void yeah()
{
cout << "yeah\n";
}
void test()
{
return yeah();
}和一个简单的无限递归循环:
void test()
{
// !!!Caution!!! This will produce an infinite loop!
return test();
}只要你在返回后写的什么都不是(就像一个空函数),return cout<<"yeah\n"就不会为这两个函数编译,因为你调用的cout的成员函数不是空函数。
发布于 2010-06-27 15:37:42
左返回节点(
->display_r_);
std::cout <<节点->value_ << std::endl;
返回display_r(节点->right_);
这段代码不起作用,因为在第一次(递归地)调用左子节点上的display_r之后,您从函数返回,因此不会显示打印,也不会显示右子节点的display_r。基本上发生的是,在所有左侧节点上递归调用该函数,直到没有左子节点的节点,然后递归调用都返回,而不打印任何值。
现在,为了回答你的问题,不仅可以在递归函数中使用return,它(通常)也是算法的“停止机制”。但是在这里,您不希望从display_r返回值,因为它不返回任何内容(空)。此外,在void函数上使用"return XXX;“是令人困惑和错误的。因为在我们的例子中,display_r只返回一个空值,所以这不会产生编译错误,但通常,当你返回一个空值时,使用" return ;“(不调用函数或值)是正确的形式。在您的例子中,递归函数的停止机制是当您“显示”一个null节点时,因此第一个返回是唯一必需的。
https://stackoverflow.com/questions/3126669
复制相似问题