简体   繁体   中英

segmentation fault in binary tree in C

I was trying to implement my code to create a binary tree in C language.The code doesn't give out any errors but during runtime it results in segmentation fault .Couldn't figure out the reason why. please help.

#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;
}

As described by @BLUEPIXY the segmentation fault is caused by parsing the value of the variable ch instead of the address of ch . In addition to this you code appears to have some logical errors.

  1. Your implementation of insert only looks at the root node and adds the new value its left or right child, depending on the root value. The desired behaviour is for insert to search down through the tree structure until it reaches a leaf node, and insert the new value here.

  2. As indicated by @BLUEPIXY the while ((*root)!=NULL) in the traverse function is equal to while (true) , as the root element is never updated. Here, again, the desired behaviour is for the traverse function to navigate the tree structure (usually from left to right) and recursively visit the children of the current node. The code below implements a simple way to achieve this by simply calling traverse on each child, without the while-loop.

  3. Finally, as @BLUEPIXY also points out, your call to free with root as argument does not release the entire tree. Free only releases the memory block pointed to by its argument. It does not recursively follow pointers within that memory block. In order to release all resources held by the tree structure you need to traverse the tree again and call free on every node.

The following code, based on your code, implements binary tree. Note that the tree is not likely to remain balanced, as it grows. To achieve a balanced binary tree you need to remodel the tree when inserting a new node.

#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;
}

Problem is with your traverse() function.

  1. when you are checking the root is NULL or not then you have missed the braces that include the printf() statement and return 0 statement;

if you dont do this then first it will check whether (root is NULL or not) if yes -> then print the statement "TREE EMPTY" and return ; if no -> it directly return from the function.

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);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM