简体   繁体   中英

Creating binary tree and passing node as pass by reference

I am trying to create a binary tree and i am new to data structure. What i have to do is:

(1) Take the size of tree (total number of nodes) at terminal.

(2) Then up to size read nodes from the user at terminal

(3) Then create Binary search tree.

Note: I have to pass the node by reference only` in the function call(No other options).

It compiles without error but i guess there is any logical problem. It gives segmentation fault when i try to insert second node in for loop (for first it works fine) but compile without errors .I am not able to predict it's due to which line of code? When I do:

How many  nodes are to be inserted ?
5
enter the nodes 
1 //I am not able to add more nodes
Segmentation fault (core dumped)

Answer in any language c/c++ or even algorithm are welcome.

My code to do so is :

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


struct node 
{
    int freq;
    struct node * left, * right;
};
typedef struct node node;
/////////////////////////////////////////////////////////////Function definitions //////////////////////////////////////////////////
insert_first_node(int data, node * * Node) 
{
  node * temp1 ;
  temp1 =  Node;
  temp1= (node * ) malloc(sizeof(node));
  temp1 -> freq = data;
  temp1 -> left = NULL;
  temp1 -> right = NULL; 
}
////////////////////////////////////////////////////////////////////
insert_beginning(int data, node * * Node) 
{
    root = * Node;
root = (node * ) malloc(sizeof(node));;
    if (root ==NULL) 
    {
        insert_first_node(data, & root);
    }
    if (data <= root -> freq) 
    {
        insert_beginning(data, & root -> left);
    } else 
    {
        insert_beginning(data, & root -> right);
    } 
    *Node = root;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
main() 
{
    int i, size, data;
    node * head;
    head = NULL;

    printf("How many  nodes are to be inserted ?\n");
    scanf("%d", & size);
    for (i = 1; i <= size; i++) 
    {
        printf("enter the nodes \n");
        scanf("%d", & data);
        insert_beginning(data, & head);
    }

}

I would write it like this (although I wouldn't necessarily use recursion, but maybe you are supposed to...):

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

typedef struct Node 
{
    int freq;
    struct Node *left;
    struct Node *right;
} Node;

///////////////////////////////////////////////////////////
// Function definitions                                  //
///////////////////////////////////////////////////////////

int insert_leaf_node(int freq, Node **parent_ptr) 
{
  Node *node;

  if ((node = malloc(sizeof *node)) == NULL)
      return -1;

  node->freq = freq;
  node->left = NULL;
  node->right = NULL; 
  *parent_ptr = node;
  return 0;
}

///////////////////////////////////////////////////////////

int insert_node(int freq, Node **parent_ptr) 
{
    Node *node = *parent_ptr;

    if (node == NULL) {
        return insert_leaf_node(freq, parent_ptr);
    }
    else if (freq <= node->freq) {
        return insert_node(freq, &node->left);
    }
    else {
        return insert_node(freq, &node->right);
    }
}

///////////////////////////////////////////////////////////

int main() 
{
    int i, size, freq;
    Node *root = NULL;

    printf("How many  nodes are to be inserted ?\n");
    scanf("%d", &size);

    for (i = 0; i < size; i++) {
        printf("enter the freq of node %d\n", i+1);
        scanf("%d", &freq);
        insert_node(freq, &root);
    }

    return 0;
}

And here's how I would write insert_node without recursion:

int insert_node(int freq, Node **parent_ptr)
{
    Node *node;

    while ((node = *parent_ptr) != NULL) {
      parent_ptr = (freq <= node->freq) ? &node->left : &node->right;
    }

    return insert_leaf_node(freq, parent_ptr);
}

You are getting segmentation fault starting from first input only. Let me clear the reason for that.
In insert_beginning function, first line is root = * Node; . Here *Node is NULL already. So root would have NULL value also. You expected that root also points to same address as *Node but this is not the case as *Node is pointing to nothing, so root and *Node are still unrelated. Now you have allocated the memory to root in previous line, but now you have assigned NULL to root . So previous assigned address to root is lost. So that is the leak memory, Dalibor is talking about.
Lets go ahead.
Now root==NULL is checked, which is true, so insert_first_node is called. There is temp1=Node , which is syntactically wrong. I think you intended temp1 = *Node . But still that is wrong as *Node is NULL , so would be temp1 . Now you are assigning value to NULL object. So next line gives segmentation fault.

The working code can be

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


struct node 
{
    int freq;
    struct node * left, * right;
};
typedef struct node node;
/////////////////////////////////////////////////////////////Function definitions //////////////////////////////////////////////////
void insert_first_node(int data, node * * Node,int direction) 
{
    node * temp1 = (node * ) malloc(sizeof(node));
    temp1 -> freq = data;
    temp1 -> left = NULL;
    temp1 -> right = NULL; 
    if(*Node == NULL)
        *Node = temp1;
    else if(direction == 1)
        (*Node)->right = temp1;
    else
        (*Node)->left = temp1;
}
////////////////////////////////////////////////////////////////////
void insert_beginning(int data, node * * Node) 
{
    node *root;
    root = * Node;
    if (root == NULL) 
    {
        insert_first_node(data,Node,0);
        return;
    }
    if (data <= root -> freq) 
    {
        if(root->left == NULL)
            insert_first_node(data,&root,0);
        else
            insert_beginning(data,&root->left);
    } else 
    {
        if(root->right == NULL)
            insert_first_node(data,&root,1);
        else
            insert_beginning(data,&root->right);
    } 
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
main() 
{
    int i, size, data;
    node * head;
    head = NULL;

    printf("How many  nodes are to be inserted ?\n");
    scanf("%d", & size);
    for (i = 1; i <= size; i++) 
    {
        printf("enter the nodes \n");
        scanf("%d", & data);
        insert_beginning(data, & head);
    }

}

It seg-faults during the insertion of your first node. If it was during the second insert, you would see the message "enter the nodes" twice.

Now to the reason. In the function insert_beginning, the first if statement does not compare root to NULL, but sets it to NULL. Since NULL is treated as false, the code inside the if is not evaluated and the execution moves to the second if statement. In it, you're trying to access freq field of root, which is set to NULL from the first if statement. So you are trying to dereference NULL pointer, which leads to the seg-fault.

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