【问题标题】:Why is the output going into infinity [closed]为什么输出进入无穷大[关闭]
【发布时间】:2020-02-20 17:47:36
【问题描述】:

这是我用来在 BST 中添加的代码。这是预购函数。为什么它会进入无穷大?我从用户那里获取关于要添加的元素的输入。但是输出进入无穷大.

    void add(){
      struct node* temp=(struct node *) malloc(sizeof(struct node));
      struct node* current=root;
      printf("\nEnter the data:\n");
      scanf("%d",&temp->data);
      while(current->left!=NULL && current->right!=NULL){
            parent=current;
        if(temp->data > parent->data){
            current=current->right;
        }
        else{
            current=current->left;
        }

      }
      if(temp->data > parent->data){
            parent->right=temp;
            parent->left=NULL;
        }
        else{
            parent->left=temp;
            parent->right=temp;
        }
    }

    void preorder(struct node* node)
    {
         if (node == NULL)
              return;

         /* first print data of node */
         printf("%d ", node->data);

         /* then recur on left subtree */
         preorder(node->left);

         /* now recur on right subtree */
         preorder(node->right);
    }

【问题讨论】:

  • 是时候学习如何使用调试器逐句执行程序了。对于这类问题,快速调试会话应该能够帮助快速找出问题。
  • @Abhiraj Kale 函数 add 具有未定义的行为,因为最初 root 可以等于 NULL。
  • add函数的某一时刻,它设置parent->leftparent->right指向同一个节点。这看起来不对。
  • temp->lefttemp->right 永远不会初始化为 NULL,因此它们将包含无效指针。

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


【解决方案1】:

函数 add 具有未定义的行为。

对于初学者来说,root 最初可以等于 NULL。所以你可能不会使用这种方法

  struct node* current=root;
  //...
  while(current->left!=NULL && current->right!=NULL){

因为尝试使用空指针访问内存。

其次是这个循环

  while(current->left!=NULL && current->right!=NULL){
        parent=current;

不处理仅包含一个不等于 NULL 的子节点的节点。

另外,您没有将创建的节点 temp 左右的数据成员设置为 NULL。

这些陈述中有一个错字

        parent->left=temp;
        parent->right=temp;

所以函数定义无效。

并且该函数应该只做一件事:将一个节点附加到树上。它不应该提示用户输入一些数据。

考虑到对根节点使用全局变量是个坏主意。

尽管如此,这里有一个使用您的方法的演示程序。我将这种方法称为 Java 方法(在 C 中,函数 add 可以更简单地编写)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

struct node
{
    int data;
    struct node *left, *right;
};

struct node *root;

_Bool add( int data )
{
    struct node *new_node = malloc( sizeof( struct node ) );
    _Bool success = new_node != NULL;

    if ( success )
    {
        new_node->data  = data;
        new_node->left  = NULL;
        new_node->right = NULL;

        if ( root == NULL )
        {
            root = new_node;
        }
        else
        {
            for ( struct node *current = root; ; )
            {
                struct node *parent = current;

                if ( data < current->data )
                {
                    current = current->left;
                    if ( current == NULL )
                    {
                        parent->left = new_node;
                        break;
                    }
                }
                else
                {
                    current = current->right;
                    if ( current == NULL )
                    {
                        parent->right = new_node;
                        break;
                    }
                }
            }
        }
    }

    return success;
}

void preorder( const struct node *node )
{
    if ( node != NULL )
    {
        printf( "%d ", node->data );
        preorder( node->left );
        preorder( node->right );
    }
}

int main(void) 
{
    srand( ( unsigned int )time( NULL ) );

    const int N = 10;

    for ( int i = 0; i < N; i++ ) add( rand() % N );

    preorder( root );

    putchar( '\n' );

    return 0;
}

程序输出可能看起来像

4 0 3 2 1 0 1 2 5 8 

下面有一个演示程序,展示了如何使用 C 方法编写函数 add。在程序中,全局变量 root 被移除并替换为局部变量 root。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

struct node
{
    int data;
    struct node *left, *right;
};

_Bool add( struct node **root, int data )
{
    struct node *new_node = malloc( sizeof( struct node ) );
    _Bool success = new_node != NULL;

    if ( success )
    {
        new_node->data  = data;
        new_node->left  = NULL;
        new_node->right = NULL;

        while ( *root != NULL )
        {
            if ( data < ( *root )->data ) root = &( *root )->left;
            else root = &( *root )->right;
        }

        *root = new_node;
    }

    return success;
}

void preorder( const struct node *node )
{
    if ( node != NULL )
    {
        printf( "%d ", node->data );
        preorder( node->left );
        preorder( node->right );
    }
}

int main(void) 
{
    struct node *root = NULL;

    srand( ( unsigned int )time( NULL ) );

    const int N = 10;

    for ( int i = 0; i < N; i++ ) add( &root, rand() % N );

    preorder( root );

    putchar( '\n' );

    return 0;
}

现在调查并比较函数 add 的两种实现。

【讨论】:

  • 谢谢,但是为什么全局声明变量不是一个好主意呢?我是初学者
  • @AbhirajKale 因为在这种情况下你不能拥有例如两棵二叉树。
【解决方案2】:

你必须用这种方式重写你的add方法,

void add()
    {
        int data;
        printf("\nEnter the data:\n");
        scanf("%d",data);
        root = insert_rec(root, data);
    }
struct node* insert_rec(struct node* current, int data)
    {


        if(current == NULL)
        {
            struct node* temp=(struct node *) malloc(sizeof(struct node));
            temp->data = data;
            current = temp;
            return current;
        }
        else
        {
            if(current->data > data)
            {
                current->left = insert_rec(current->left, data);
            }
            else
            {
                current->right = insert_rec(current->right, data);
            }
        }
        return current;
    }

这是 BST 插入的递归方式。 希望这可能会有所帮助:)

【讨论】:

  • 您忘记将temp-&gt;lefttemp-&gt;right 设置为NULL
猜你喜欢
  • 1970-01-01
  • 2014-10-30
  • 2022-01-10
  • 1970-01-01
  • 2016-10-16
  • 1970-01-01
  • 2023-03-16
  • 2018-12-03
相关资源
最近更新 更多