该函数的行为不正确,因为它在这些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 );
return (lookup(n,x->right));
而不是仅仅写lookup(n,x->right);
。 - Stef