C语言中二叉树中的分段错误

时间:2017-07-06 20:28:51

标签: c

我正在尝试实现我的代码来用C语言创建二叉树。代码没有给出任何错误,但在运行时它会导致分段错误。无法找出原因。请帮忙。

#include<stdio.h>
#include<malloc.h>

struct node{
    int value;
    struct node *left;
    struct node *right;
}*root = NULL;

struct node* create(int val)
{
    struct node *ptr;
    ptr = (struct node*)malloc(sizeof(struct node));
    ptr->value = val;
    ptr->left = NULL;
    ptr->right = NULL;
    return ptr;
}

void insert(int val)
{
    if(root == NULL)
    {
        root=create(val);
    }
    else if(val < (root)->value)
    {
        (root)->left = create(val);
    }
    else
    {
        (root)->right = create(val);
    }
}

void traverse(struct node** root)
{   
    if(*root==NULL)
        printf("TREE EMPTY");
        return 0;
    while((*root)!=NULL)
    {
        printf("%d",(*root)->value);
        traverse((*root)->left);
        traverse((*root)->right);
    }
}

int main()
{
    int val;
    char ch='y';
    while(ch=='y')
    {
        scanf("%d",&val);
        insert(val);
        printf("Want to insert more elements ?(y or n) =");
        scanf("%c",ch);
    }
    traverse(&root);
    free(root);
    return 0;
}

2 个答案:

答案 0 :(得分:1)

如@BLUEPIXY所述,分段错误是由解析变量ch的值而不是ch的地址引起的。除此之外,您的代码似乎也有一些逻辑错误。

  1. insert的实现仅查看根节点,并根据根值将新值添加到其左或右子节点。所需的行为是插入向下搜索树结构,直到它到达叶节点,并在此处插入新值。

  2. 如@BLUEPIXY所示,while ((*root)!=NULL)函数中的traverse等于while (true),因为根元素永远不会更新。在这里,同样,期望的行为是traverse函数导航树结构(通常从左到右)并递归地访问当前节点的子节点。下面的代码实现了一种简单的方法来实现这一点,只需在每个子节点上调用遍历,而不使用while循环。

  3. 最后,正如@BLUEPIXY也指出的那样,以free作为参数调用root并不会释放整个树。 Free仅释放其参数指向的内存块。它不会递归地跟随该内存块中的指针。为了释放树结构所拥有的所有资源,您需要再次遍历树并在每个节点上调用free

  4. 以下代码基于您的代码实现二叉树。请注意,随着树的增长,树不太可能保持平衡。要实现平衡的二叉树,您需要在插入新节点时重新构建树。

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct node{
        int value;
        struct node *left;
        struct node *right;
    } node;
    
    node *root = NULL;
    
    node* create(int val)
    {
    
        node *ptr;
        ptr = (node*)malloc(sizeof(node));
        ptr->value = val;
        ptr->left = NULL;
        ptr->right = NULL;
        return ptr;
    }
    
    void insert_(node *root, int val)
    {
      if (val < root->value)
      {
        if (root->left != NULL)
        {
            insert_(root->left, val);
            } else {
            root->left = create(val);
            }
        }
        else
        {
            if (root->right != NULL)
            {
                insert_(root->right, val);
            } else {
                root->right = create(val);
            }
        }
    }
    
    void insert(int val)
    {
        if(root == NULL)
        {
            root = create(val);
        }
        else
        {
            insert_(root, val);
        }
    }
    
    void traverse(node *root)
    {
        if(root == NULL)
        {
            printf("E");
            return;
        }
        printf("%d (", root->value);
        traverse(root->left);
        printf( ") (");
        traverse(root->right);
        printf( ")");
    }
    
    void free_tree(node *root)
    {
          if (root == NULL) {
                return;
          }
          free_tree(root->left);
          free_tree(root->right);
          free(root);
    }
    
    int main()
    {
          int val;
          char ch='y';
          while(ch=='y')
          {
                scanf("%d",&val);
                insert(val);
                printf("Want to insert more elements ?(y or n) =");
                scanf(" %s", &ch);
          }
          traverse(root);
          free_tree(root);
          return 0;
    }
    

答案 1 :(得分:0)

问题出在您的traverse()函数上。

  1. 在检查根是否为NULL时,您错过了包含printf()语句和return 0语句的花括号;

如果您不这样做,那么它将首先检查 是否(root为NULL) 如果是->然后打印语句“ TREE EMPTY”并返回; 如果没有->它直接从函数返回。

void traverse ( struct node **root )
{
    if ( *root == NULL )
    {
        printf ("TREE EMPTY");
        return 0;
    }
    while ((*root) != NULL )
    {
        printf ("%d", (*root) -> value);
        traverse ((*root) -> left);
        traverse ((*root) -> right);
    }
}