【问题标题】:Binary Search Tree does not recognize values properly二叉搜索树无法正确识别值
【发布时间】:2017-10-18 11:06:07
【问题描述】:

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

我在这里错过了什么?

提前致谢。

【问题讨论】:

  • 如果您还没有,那么这是学习如何使用调试器以及如何使用它(和其他技术)进行调试的最佳时机 你的程序。我建议您花点时间阅读 Eric Lippert 的 How to debug small programs
  • 并且在编译时也会出现警告。例如,当您应该返回新节点时,您不会从 getNewNode 返回任何内容。
  • 尝试修复代码的缩进 - 这将有助于您和代码的未来读者。

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


【解决方案1】:

你错过了

num =scanf("%d");

没有做你认为它做的事情(scanf 返回成功转换的项目数或在EOF 上返回-1)。您没有将编译器的警告级别调高到足以告诉您需要

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

在您损坏的程序中,scanf() 恰好返回 1(因为它转换了 1 个项目并将其写入随机内存),并且由于树中有一个 1,所以您总是得到 true。

【讨论】:

    【解决方案2】:

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

    return newNode;
    

    在该函数的末尾。这是fixed example on ideone

    【讨论】:

    • 请在您的答案中添加scanf("%d",&amp;num);。因为修复return newNode;后也是一个问题
    • 我已经从In addition to the error pointed out by @Jens 开始回答,我意识到这是一个问题,但我没有发现这个错误。 Jens 的回答对此提供了足够的详细信息,我认为在我的回答中重复他的解释没有价值
    【解决方案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是错误的。考虑到对于二叉搜索树,通常使用运算符&lt;而不是运算符&lt;=

    这些陈述

    root->left = InsertNew(root->left,data);
    

    root->right = InsertNew(root->right,data); 
    

    没有意义并覆盖不应实际更改的节点的root-&gt;leftroot-&gt;right 的值。此外,创建的节点也可以等于 NULL,在这种情况下,原始根节点也将被 NULL 覆盖。

    最好是通过指针引用原始根节点。

    您还应该使用operator &lt; 而不是operator &lt;=

    函数定义如下所示

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-27
      • 2011-09-16
      • 2020-03-16
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 2019-10-28
      相关资源
      最近更新 更多