二进制搜索树无法正确识别值

时间:2017-10-18 11:06:07

标签: c data-structures binary-search-tree

我正在尝试使用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;
}

我在这里缺少什么?

提前致谢。

3 个答案:

答案 0 :(得分:5)

你错过了

num =scanf("%d");

不会按照您的想法执行操作(scanf返回成功转换的项目数或EOF上的-1)。您没有将编译器的警告级别设置得足够高,以告诉您需要

if (scanf ("%d", &num) != 1) {
    /* complain */
}

在你破碎的程序中,scanf()碰巧返回1(因为它转换了1个项目并将其写入随机存储器)并且因为树中有1个,所以你总是得到真的。

答案 1 :(得分:3)

除了@Jens指出的错误之外,您没有从getNewNode返回值。添加声明:

return newNode;

在该功能的最后。这是fixed example on ideone

答案 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->leftroot->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的严格比较将不起作用。