问题描述
我正在尝试为二进制搜索树实现查找功能。如果我查找树的根,它的确会返回true,但是当我查找树中的其他条目时,它会返回false。当我对其进行调试时,该函数似乎返回1,但随后将继续运行,然后最后返回0。据我了解,该函数应在返回任何值后立即终止,因此我不确定为什么会发生这种情况。
int lookup(int n,struct node* x)
{
if (x->data==n)
{
return 1;
}
else if (x->left==NULL && x->right==NULL)
{
return 0;
}
else if (n>x->data && x->right!=NULL)
{
lookup(n,x->right);
}
else
{
lookup(n,x->left);
}
return 0;
}
解决方法
您的递归lookup
调用返回的值(即lookup(n,x->right);
和lookup(n,x->left);
)将被忽略,即使它是正确的值。
这是因为在函数结束时(即从这些调用之一返回后),您无条件return 0;
。
要用lookup(n,x->XXX);
代替return lookup(n,x->XXX);
。
该函数的行为不正确,因为它在这些if语句中不返回任何内容
else if (n>x->data && x->right!=NULL)
{
lookup(n,x->right);
}
else
{
lookup(n,x->left);
}
该控件将被传递到if-else语句之后的最后一个return语句
return 0;
但是如果您要更新功能
int lookup(int n,struct node* x)
{
if (x->data==n)
{
return 1;
}
else if (x->left==NULL && x->right==NULL)
{
return 0;
}
else if (n>x->data && x->right!=NULL)
{
return lookup(n,x->right);
}
else
{
return lookup(n,x->left);
}
return 0;
}
尽管如此,该函数可以调用未定义的行为,因为它不检查指针x
是否等于NULL
。
例如,假设x->data
不等于n
,而n
小于x->data
。另外,我们假设x->left
等于NULL
,而x->right
不等于NULL
。
在这种情况下,第一个if语句的子语句
if (x->data==n)
{
return 1;
}
将不会执行。
第二个if语句的子语句也将不会执行,因为x->right
不等于NULL
。
else if (x->left==NULL && x->right==NULL)
{
return 0;
}
第三个if语句将存在相同的问题。
因此控件将在最后的else语句内传递
else
{
lookup(n,x->left);
}
,其中使用空指针x->left
调用该函数。因此,在函数的第二次调用中,您将尝试使用空指针访问内存
if (x->data==n)
{
return 1;
}
可以通过以下方式编写函数。请注意,由于该函数不会更改树本身,因此它的第二个参数应使用限定符const
声明。
int lookup( int n,const struct node *x )
{
if ( x == NULL )
{
return 0;
}
else if ( n < x->data )
{
return( n,x->left );
}
else if ( x->data < n )
{
return ( n,x->right );
}
else
{
return 1;
}
}
通常,这样的函数也用第一个参数声明,该参数指定指向节点(指向树)的指针,第二个参数指定搜索的对象。就像
int lookup( const struct node *x,int n );
甚至喜欢
_Bool lookup( const struct node *x,int n );
,
您进行了递归调用,但您不返回其结果!
您的代码最简单的递归版本是:
int lookup(int n,struct node* x)
{
if (x == NULL)
return 0;
if (n == x->data)
return 1;
if (n < x->data)
return lookup(n,x->left);
else
return lookup(n,x->right);
}
只要它没有脱离分支,它就会测试当前节点-找到该值时,将返回1,否则查找将跳入左分支或右分支。路径结束时(x == NULL
,找不到该值,并返回0。
结果从递归返回时向上传播。
最简单的迭代版本:
int lookup(int n,struct node* x)
{
while (x != NULL)
{
if (n == x->data)
return 1;
if (n < x->data)
x = x->left;
else
x = x->right;
}
return 0;
}
它的工作方式与递归类似,不同之处在于它不会陷入递归,而只是将x
指针移到树下。如果在分支端之前找到该值,则返回1。否则,当扫描经过树叶时,结果为0。