我正在尝试使用C实现二进制搜索树。在此代码中,我向树中添加了几个值,然后尝试检查这些值是否在树中。但我尝试的代码总是返回true。
我已多次检查过。我还在学习C编程。
这是我的代码。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct BSTnode {
int data;
struct BSTnode *left;
struct BSTnode *right;
} BSTnode;
BSTnode *getNewNode(int data){
BSTnode *newNode = (BSTnode*)malloc(sizeof(BSTnode));
newNode->data=data;
newNode->left=newNode->right=NULL;
}
BSTnode* InsertNew(BSTnode *root,int data){
if(root == NULL){
root = getNewNode(data);
}
else if(data <= root->data){
root->left = InsertNew(root->left,data);
} else{
root->right = InsertNew(root->right,data);
}
return root;
}
bool search(BSTnode *root, int data){
if(root== NULL) return false;
else if(root->data == data) return true;
else if (data <= root->data) return search(root->left,data);
else return search(root->right,data);
}
int main()
{
//node to store root
BSTnode *root = NULL;
root = InsertNew(root,34);
root = InsertNew(root,4);
root = InsertNew(root,3);
root = InsertNew(root,1);
int num;
printf("enter a number : \n");
num =scanf("%d");
if(search(root,num)==true){
printf("found");
}else{
printf("not found");
}
return 0;
}
我在这里缺少什么?
提前致谢。
答案 0 :(得分:5)
你错过了
num =scanf("%d");
不会按照您的想法执行操作(scanf返回成功转换的项目数或EOF
上的-1)。您没有将编译器的警告级别设置得足够高,以告诉您需要
if (scanf ("%d", &num) != 1) {
/* complain */
}
在你破碎的程序中,scanf()碰巧返回1(因为它转换了1个项目并将其写入随机存储器)并且因为树中有1个,所以你总是得到真的。
答案 1 :(得分:3)
答案 2 :(得分:3)
对于根据C标准的初学者,不带参数的函数main
应声明为
int main( void )
函数getNewNode
BSTnode *getNewNode(int data){
BSTnode *newNode = (BSTnode*)malloc(sizeof(BSTnode));
newNode->data=data;
newNode->left=newNode->right=NULL;
}
具有未定义的行为,因为它返回任何内容但返回类型为BSTnode *
。
该功能可以通过以下方式定义
BSTnode * getNewNode( int data )
{
BSTnode *newNode = ( BSTnode * )malloc( sizeof( BSTnode ) );
if ( newNode != NULL )
{
newNode->data = data;
newNode->left = newNode->right = NULL;
}
return newNode;
}
函数InsertNew
是错误的。考虑到对于二叉搜索树,通常使用运算符<
而不是运算符<=
。
这些陈述
root->left = InsertNew(root->left,data);
和
root->right = InsertNew(root->right,data);
没有意义并且会覆盖不会实际更改的节点的root->left
和root->right
的值。此外,创建的节点可以等于NULL,在这种情况下,原始根节点也将被NULL覆盖。
最好通过指针传递原始根节点。
另外,您应该使用operator <
代替operator <=
。
函数定义可以采用以下方式
BSTnode * InsertNew( BSTnode **root,int data )
{
if ( *root == NULL )
{
*root = getNewNode( data );
return *root;
}
else if ( data < ( *root )->data )
{
return InsertNew( &( *root->left ), data );
}
else
{
return InsertNew( &( *root->right ), data );
}
}
并且可以像
一样调用该函数InsertNew( &root, 34 );
没有将返回指针分配给根节点。如果需要,可以在if语句中检查返回值。
如果您不希望树中有重复值,则可以按以下方式编写该函数
BSTnode * InsertNew( BSTnode **root,int data )
{
if ( *root == NULL )
{
*root = getNewNode( data );
return *root;
}
else if ( data < ( *root )->data )
{
return InsertNew( &( *root->left ), data );
}
else if ( ( *root )->data < data )
{
return InsertNew( &( *root->right ), data );
}
else
{
return NULL;
}
}
相应地,函数search
应该被定义为
bool search( BSTnode *root, int data )
{
if ( root == NULL )
{
return false;
}
else if ( data < root->data )
{
return search( root->left, data );
}
else if ( root->data < data )
{
return search( root->right, data );
}
else
{
return true;
}
}
在本声明中使用函数scanf
num =scanf("%d");
错了。
正确的通话看起来像
printf( "enter a number : " );
scanf( "%d", &num );
您还可以使用if语句中的条件
来检查调用是否成功if ( scanf( "%d", &num ) == 1 )
{
//...
}
在退出程序之前,你应该为树释放所有已分配的内存。
一般情况下,最好使用以下条件
if(search(root,num) ){
而不是与真实
的严格比较if(search(root,num)==true){
因为如果函数将被重写,在成功的情况下它将返回任何非零值,那么与true
的严格比较将不起作用。