Inserting element in binary tree - c

The code is for inserting an element in a binary tree using level order traversal. I'll first tell u how it works. It first goes through the nodes in each level and if there is any node which doesn't have both children it inserts the node as a child to that node and it use's queue for storing and retrieving the nodes addresses. My problem is that every time I call the create function the root value which is passed is always null even after inserting a node the root value is not changed and it's still a null. I am unable to figure out what's wrong in this. Can anyone help me out?
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *left,*right;
}*root;
struct queue
{
int capacity,rear,front;
struct node **qu;
};
void enqueue(struct queue *q,struct node *n)
{
q->front=(++(q->front))%q->capacity;
(q->qu)[q->front]=n;
if(q->rear==-1)
q->rear++;
}
struct node* dequeue(struct queue *q)
{
struct node *temp;
temp=q->qu[q->rear];
if(q->front==q->rear)
q->front=q->rear=-1;
else
q->rear=(++(q->rear))%q->capacity;
}
int isempty(struct queue *q)
{
return(q->rear==-1);
}
struct queue* create(unsigned int capacity)
{
struct queue *p;
p=(struct queue*)malloc(sizeof(struct queue));
p->capacity=capacity;
p->front=p->rear=-1;
p->qu=(struct node**)malloc(sizeof(struct node)*capacity);
return p;
}
void insert(struct node *root)
{
int n;
struct node *p,*q;
struct queue *tmp;
p=(struct node*)malloc(sizeof(struct node));
p->left=p->right=NULL;
scanf("%d",&n);
p->data=n;
if(root==NULL)
{
root=p;
return;
}
tmp=create(20);
enqueue(tmp,root);
while(isempty(tmp))
{
q=dequeue(tmp);
printf("%d %d\n",p,root);
if((!q->right)||(!q->left))
{
if(!q->right)
q->right=p;
else
q->left=p;
return;
}
else
{
enqueue(tmp,q->left);
enqueue(tmp,q->right);
}
}
}
void traverse(struct node *root)
{
if(!root)
return;
traverse(root->left);
printf("%d ",root->data);
traverse(root->right);
}
void main()
{
int i,n;
while(1)
{
printf("1.insert\n2.exit\n");
scanf("%d",&n);
switch(n)
{
case 2:goto end;
case 1:insert(root);
}
}
end:
traverse(root);
}
Thanks.

You've defined root as a global variable, but your insert function also defines it's own local version of root which takes precedence. Because you're passing root in by value rather than reference, changing it's value has no effect. You have two options on how to fix this.
Pass root by reference
You change insert to be void insert(struct node **root) and then replace all instances of root in the function with (*root). You'll also need to pass a pointer to root when you call it - insert(&root)
Return the new value of root
Change the return type to struct node * and make sure you return root at the end and at any point where you're already returning from the function. When you call it you'll assign the return value to root like root=insert(root)
Both are equally valid options.

Related

Program crashes when inserting a node in a binary tree

I created the following library to insert,delete,search and print nodes in a binary tree.
#include <stdlib.h>
struct NODE
{
int code;
char subject[20];
struct NODE *left;
struct NODE *right;
};
void InOrder(struct NODE *R)
{
if (R==NULL)
return;
InOrder(R->left);
printf("%d %s\n",R->code,R->subject);
InOrder(R->right);
}
void PreOrder(struct NODE *R)
{
if (R==NULL)
return;
printf("%d %s\n",R->code,R->subject);
InOrder(R->left);
InOrder(R->right);
}
void PostOrder(struct NODE *R)
{
if (R==NULL)
return;
InOrder(R->left);
InOrder(R->right);
printf("%d %s\n",R->code,R->subject);
}
struct NODE *Search(struct NODE *R,int CODE,struct NODE **father)
{
if(R==NULL)
return NULL;
if(R->code==CODE)
{
*father=R;
return R;
}
if (CODE<R->code)
return Search(R->left,CODE,father);
else
return Search(R->right,CODE,father);
}
struct NODE * CreateNode(struct NODE T)
{
struct NODE *tmp;
tmp=(struct NODE *)malloc(sizeof(T));
*tmp=T;
tmp->left=tmp->right=NULL;
return tmp;
}
int Insert(struct NODE **R,struct NODE ND)
{
struct NODE *cur,*fath=NULL;
cur=Search(*R,ND.code,&fath);
if (cur)
return 0;
cur=CreateNode(ND);
if(fath==NULL)
*R=cur;
else
if(fath->code>ND.code)
fath->left=cur;
else
fath->right=cur;
return 1;
}
struct NODE *MinOfMax (struct NODE *ND)
{
struct NODE *tmp;
if (ND==NULL)
return NULL;
if(ND->right==NULL)
return NULL;
tmp=ND->right;
while(tmp->left!=NULL)
tmp=tmp->left;
return tmp;
}
struct NODE* Delete(struct NODE *R, int code)
{
if (R==NULL)
return R;
if (code<R->code)
R->left=Delete(R->left,code);
else if (code>R->code)
R->right=Delete(R->right,code);
else
{
if (R->left==NULL)
{
struct NODE *temp=R->right;
free(R);
return temp;
}
else if (R->right==NULL)
{
struct NODE *temp=R->left;
free(R);
return temp;
}
struct NODE *temp=MinOfMax(R->right);
R->code=temp->code;
R->right=Delete(R->right,temp->code);
}
return R;
}
When i try to insert a node in the binary tree,the program crashes.Here is my main:
int main(int argc,char* argv[])
{
typedef struct NODE NODE;
NODE *root=NULL;
NODE tmp;
Insert(&root,tmp);
return 0;
}
I tried to assign static values (for example code=100 and subject="Physics") but still the program crashes.Should i malloc something,change anything in my header file or do something entirely different?I'm stuck here for hours without finding any solution.Most insert functions out there assume that i only have one integer as data in the node,but i need to pass the entire node.
Your code basically does nothing. It seems you copy-pasted it from somewhere. I tried to figure it out and here's a code example. Basically you've to initializate a new node in the main when you try to insert it.
Note that's just an example, i didn't a full test.
int main(int argc,char* argv[])
{
typedef struct NODE NODE;
NODE *root=NULL;
NODE *tmp = malloc(sizeof(struct NODE));
tmp->code = 1; /*Just a number*/
strcpy(tmp->subject,"prova"); /*Put something in it*/
Insert(&root,*tmp); /* Try to insert it*/
PreOrder(root); /*Try to see if it has been inserted*/
return 0;
}
Your tmp node, which is going to be the newly inserted node is used uninitialized in your main(). Your compiler could have warned you for this, if you had used -Wall flag.
So let's take a look in your insert function:
int Insert(struct NODE **R, struct NODE ND)
{
struct NODE *cur,*fath=NULL;
cur = Search(*R, ND.code, &fath); // ND.code is junk, since ND is uninitialized
...
return 1;
}
which likely causes the segmentation fault.
root is too, you could initialize it to NULL in main().
Not the cause of your problem, but Do I cast the result of malloc? No.

Connect preorder predecessor with its successor in a binary search tree

Actually in an interview i was asked to write a code through which every node in a binary search tree is having a extra pointer namely "next" we have to connect this pointer of every node to its pre order successor ,can any one suggest me the code as i was not able to do so. the tree nodes has above structure :-
struct node {
int data ;
struct node *left,*right;
struct node *next; //this pointer should point to pre order successor
};
thank you .
Cracked the the solution thanks to you guys ,below is the whole code written in c :-
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *left,*right,*next;
};
struct node* getNode(int data)
{
struct node* temp=(struct node*)malloc(sizeof(struct node));
temp->left=temp->right=NULL;
temp->data=data;
return temp;
}
void insert(struct node**root,int data)
{
if(!*root)
{
*root=(struct node*)malloc(sizeof(struct node));
(*root)->left=(*root)->right=NULL;
(*root)->data=data;
}
else if(data<(*root)->data)
insert(&((*root)->left),data);
else if(data>(*root)->data)
insert(&((*root)->right),data);
}
struct node* preorderSuccessor(struct node* root,struct node* p)
{
int top,i;
struct node *arr[20];
if(!root || !p)
return NULL;
if(p->left)
return p->left;
if(p->right)
return p->right;
top=-1;
while(root->data!=p->data)
{
arr[++top]=root;
if(p->data<root->data)
root=root->left;
else
root=root->right;
}
for(i=top;i>=0;i--)
{
if(arr[i]->right)
{
if(p!=arr[i]->right)
return arr[i]->right;
}
p=arr[i];
}
return NULL;
}
void connect(struct node* parent,struct node *r)
{
if(r)
{ connect(parent ,r->left);
r->next = preorderSuccessor(parent,r);
connect(parent,r->right);
}
}
int main()
{
struct node* root=NULL,*temp=NULL;
int arr[]={10,11,2,3,9,8,4,5},size,i;
size=sizeof(arr)/sizeof(arr[0]);
for(i=0;i<size;i++)
insert(&root,arr[i]);
connect(root,root);
struct node *ptr = root;
while(ptr){
// -1 is printed if there is no successor
printf("Next of %d is %d \n", ptr->data, ptr->next? ptr->next->data: -1);
ptr = ptr->next;
}
return 0;
}
As Eugene said: So traverse the tree with preorder traversal and connect. To do that, you need to know which node, if any, you visited last.
You can do that with the usual recursive approach by passing a reference to the previous node. This must be the address of a variable that is valid throughout the recursion, because the previous node is not necessarily closer to the root. You could use a global variable, but a variable created in a wrapper function may be better:
void connect_r(struct node *node, struct node **whence)
{
if (node) {
if (*whence) (*whence)->next = node;
*whence = node;
connect_r(node->left, whence);
connect_r(node->right, whence);
}
}
void connect(struct node *head)
{
struct node *p = NULL;
connect_r(head, &p);
if (p) p->next = NULL;
}
The pointer p in connect, whose address is passed to the recursive function connect_r holds the node whose next pointer should be updated next. The update doesn't happen on the first visited node. and the next member of the last visited node must explicitly be set to NULL after the recursion.
Alternatively, you can connect the nodes iteratively by using a stack:
void connect(struct node *head)
{
struct node *p = NULL;
struct node **prev = &p;
struct node *stack[32]; // To do: Prevent overflow
size_t nstack = 0;
if (head) stack[nstack++] = head;
while (nstack) {
struct node *node = stack[--nstack];
*prev = node;
prev = &node->next;
if (node->right) stack[nstack++] = node->right;
if (node->left) stack[nstack++] = node->left;
}
*prev = NULL;
}
The connected next pointers are a snapshot of the current tree. Insertions, deletions and rearrangements of nodes will render the next chain invalid. (But it can be made valid again by calling connect provided that the tree's left and right links are consistent.)

Implementing the Binary Tree in C

I am trying to implement the Binary tree in C.Firstly inserting the values and then traversing them into the Preorder.But when i call the function preorder() then it's giving me infinite loop with only last value inserted.
I am using following code:
struct node* insert(struct node *root,int num);
void preorder(struct node *root);
struct node *root=NULL;
int count=1;
struct node {
struct node *lchild;
struct node *rchild;
int data;
};
int main(){
root=insert(root,1);
//root=insert(root,2);
preorder(root);
return;
}
struct node* insert(struct node *root,int num){//insert a node into tree
//struct node *q;
if(root==NULL)
{
root=(struct node*)malloc(sizeof(struct node));
root->data=num;
root->lchild=NULL;
root->rchild=NULL;
//root=q;
count++;
}
else{
if(count % 2==0){
root->lchild=insert(root->lchild,num);
}
else{
root->rchild=insert(root->rchild,num);
}
}
return(root);
}
void preorder(struct node *root){
while(root!=NULL){
printf("%d\t",root->data);
preorder(root->lchild);
preorder(root->rchild);
}
}
here i am inserting only 1 value initially but the bug occurs.So in insert() there should not be any mistake,something correction should be done in preorder() or main()..what it can be?
I am not sure what preorder() should do, but this line causes the endless loop:
while(root!=NULL){
I guess you meant to write if not while
You need an if statement not a while statement in your preorder function.
while(root!=NULL){ //This is causing the infinite loop
In the loop body, you do not change the root pointer at any point so, if the condition is ever true, which it is for the root element, it will never come out of the loop.
It should instead be :
if(root!=NULL){
You have to write if rather than while so that the recursive loop had an base condition and it ends somewhere.
In your code instead of writing if(root!=NULL) write while(root!=NULL)

linked list program

I am expecting the below linked list program to print 1
but its not.can anyone figure out why?
#include<stdio.h>
#include <stdlib.h>
#include<conio.h>
struct node
{
int data;
struct node * link;
};
typedef struct node NODE;
void display(NODE *);
void add(NODE *,int );
int main()
{
NODE *head=NULL;
add(head,1);
display(head);
printf("\n");
getch();
return 0;
}
void display(NODE *pt)
{
while(pt!=NULL)
{
printf("element is");
printf("%d",pt->data);
pt=pt->link;
}
}
void add(NODE *q,int num)
{
NODE *temp;
temp = q;
if(q==NULL)
{
q=(NODE *)malloc(sizeof(struct node));
temp = q;
}
else
{
while((temp=temp->link)!=NULL);
temp->link = (NODE *)malloc(sizeof(struct node));
temp=temp->link;
}
temp->data = num;
temp->link = NULL;
}
Your local variable head in main() is not modified by your add() function. This means you are calling display() with a parameter of NULL.
You'll need to pass a NODE **q into add, then update it in add().
Your add method when called first time (when head == NULL) should add the first node to the list thus changing head to point to the newly allocated node.
But this does not happen as add does not communicate back the changed head to the caller.
To fix this you can either return the modified head from the function:
// call as before but assign the return value to head.
head = add(head,1);
.....
// return type changed from void to NODE *
NODE* add(NODE *q,int num)
{
// make the changes as before
// return the head pointer.
return q;
}
or you can pass the pointer head by address to the function add as:
// pass the address of head.
add(&head,1);
.....
// change type of q from NODE * to NODE **
void add(NODE **q,int num)
{
// same as before but change q to *q.
// any changes made to the list here via q will be visible in caller.
}
The add() function is modifying the q argument, but it is passing it by value. Then head remains NULL after the add() call.
The problem is in signature of add method, to make your program work you should pass pointer to pointer of NODE, like this
void add(NODE **,int );
and work with him.
Then in case
if(*q==NULL)
you can allocate memory and replace NULL pointer to new HEAD
by it
*q=(NODE*)malloc(sizeof(struct node));
So it will work.
The problem is when you allocate memory you just replace local copy of null pointer to NODE but it doesn't affect head in main function.
int main()
{
NODE *head=NULL;
add(head,1);
display(head);
NODE *head is local to main. It's value is NULL. You pass the value NULL to add, which then creates a NODE and sets its data to 1. You then return to main... ...where head is STILL NULL. You need to pass the address of head, so that it's actual value is changed in add(). You also need to change add() to work with a pointer.
Main should return EXIT_SUCCESS or EXIT_FAILURE. Don't typedef struct node; it's harmful to readability and you get no abstraction here from using it.
When you call Add the new head pointer never gets returned. So it still points to NULL.
Ah... you're getting tripped up by the pointers...
Essentially, if you want to modify "head", you need to send a reference to THAT... otherwise you are just modifying the pointer... Change your code to this:
#include<stdio.h>
#include <stdlib.h>
#include<conio.h>
struct node
{
int data;
struct node * link;
};
typedef struct node NODE;
void display(NODE *);
void add(NODE **,int );
int main()
{
NODE *head=NULL;
add(&head,1);
display(head);
printf("\n");
getch();
return 0;
}
void display(NODE *pt)
{
while(pt!=NULL)
{
printf("element is ");
printf("%d",pt->data);
pt=pt->link;
}
}
void add(NODE **q,int num)
{
NODE *temp;
temp = *q;
if(*q==NULL)
{
*q=(NODE *)malloc(sizeof(struct node));
temp = *q;
}
else
{
while((temp=temp->link)!=NULL);
temp->link = (NODE *)malloc(sizeof(struct node));
temp=temp->link;
}
temp->data = num;
temp->link = NULL;
}

Using Pass by reference with linked lists

So I've use pass by reference on my linked list code but the problem is it's not printing soo how do I actually fix this?
my code:
#include<stdio.h>
#include<stdlib.h>
struct node
{
int x;
struct node *next;
};
void add(struct node **root, int x)
{
struct node *conductor;
if(root==NULL)
{
(*root)=malloc(sizeof(struct node));
(*root)->x=x;
(*root)->next=NULL ;
}
else
{
conductor = *root;
while(conductor->next!=NULL)
{
conductor = conductor -> next;
}
conductor->next=malloc(sizeof(struct node));
conductor->next->x=x;
conductor->next->next=NULL;
}
}
void display(struct node *root)
{
struct node *conductor;
conductor=root;
while(conductor!=NULL)
{
printf("%d",conductor->x);
conductor = conductor ->next;
}
}
int main()
{
struct node *root;
root=NULL;
add(&root,5);
add(&root,4);
display(root);
free(root);
system("pause");
}
In better form
http://codepad.org/CPdUvK0x
Isn't it all nodes in my program are linked?
void add(struct node **root, int x)
{
struct node *conductor;
if(root==NULL)
That should be if (*root == NULL)
Since you're calling add(&root... root will never be NULL.
The check:
if(root==NULL)
should be
if(*root==NULL)
as root is being passed by address.
Also you do free(root) to free the entire list which is incorrect as it frees only the first node and makes the other nodes unreachable causing memory leak. To fix this you need to free the nodes one by one as:
struct node *tmp = root;
while(root) {
tmp = root->next;
free(root);
root = tmp;
}
the problem is in add():
if(root==NULL)
this test is wrong: root being passed by reference is never NULL (see in the main, it contains the address of the root node). you should correctly test if the rrot node is NULL:
if (*root == NULL)
i would also add that your way of freeing the memory allocated for the ist is wrong:
free(root)
will only free the root node, but will leak the child nodes...

Resources