Inorder tree traversal in binary tree in C - c

In the below code, I'am creating a binary tree using insert function and trying to display the inserted elements using inorder function which follows the logic of In-order traversal.When I run it, numbers are getting inserted but when I try the inorder function( input 3), the program continues for next input without displaying anything. I guess there might be a logical error.Please help me clear it.
Thanks in advance...
#include<stdio.h>
#include<stdlib.h>
int i;
typedef struct ll
{
int data;
struct ll *left;
struct ll *right;
} node;
node *root1=NULL; // the root node
void insert(node *root,int n)
{
if(root==NULL) //for the first(root) node
{
root=(node *)malloc(sizeof(node));
root->data=n;
root->right=NULL;
root->left=NULL;
}
else
{
if(n<(root->data))
{
root->left=(node *)malloc(sizeof(node));
insert(root->left,n);
}
else if(n>(root->data))
{
root->right=(node *)malloc(sizeof(node));
insert(root->right,n);
}
else
{
root->data=n;
}
}
}
void inorder(node *root)
{
if(root!=NULL)
{
inorder(root->left);
printf("%d ",root->data);
inorder(root->right);
}
}
main()
{
int n,choice=1;
while(choice!=0)
{
printf("Enter choice--- 1 for insert, 3 for inorder and 0 for exit\n");
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("Enter number to be inserted\n");
scanf("%d",&n);
insert(root1,n);
break;
case 3:
inorder(root1);
break;
default:
break;
}
}
}

Your insert accepts a pointer to a node, which is local to the scope of the function. After insert returns, the root it was called upon remains unchanged. And you get a leak.
If you want the changes insert does to be visible outside of it, start by changing its signature
void insert(node **root,int n)
And calling it like so:
void insert(&root1, n);
That way, it will modify root1 and not a copy of it.
As a rule of thumb, if a function needs to modify something, it should be passed a pointer to it. You function needs to modify a node*, so it should be passed a node**.
EDIT
As unwind pointed out, you could also return the root as a means of updating it
root1 = insert(root1, n);
This of course works only if you need to modify one object.

Your allocation code is off, root1 will always stay NULL since the malloc result is only assigned to a local variable. Pass root in as a pointer to pointer.
Additionally you unconditionally malloc left and right, even though there might already be data there, you should call insert immediately and have the called insert handle the malloc just like for root. Again with a pointer to pointer of course.
Finally you else root->data = n doesn't make any sense, it's already n. And I presume you don't want duplicates in your tree? If you do you need to change your code.

Pass reference of node * to the insert() so that when new node is allocated, its appropriately updated.
Also, in your insert() function, don't allocate while moving into below tree. If you allocate then your code tries to check the value on that node and proceed again, which is not correct.
Updated code would be:
void insert(node **root_ptr,int n)
{
if(root==NULL) //for the first(root) node
{
root=(node *)malloc(sizeof(node));
root->data=n;
root->right=NULL;
root->left=NULL;
*root_ptr = root;
}
else
{
if(n<(root->data))
{
//root->left=(node *)malloc(sizeof(node));
insert(&root->left,n);
}
else if(n>(root->data))
{
//root->right=(node *)malloc(sizeof(node));
insert(&root->right,n);
}
else
{
root->data=n;
}
}
}
From main() call it as insert(&root1,n);

Related

C programming: I have an error in creating a binary search tree using C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I need to create a c program for BST but I can't create left child or right child for the root node. Creation of root node is ok. I can also search the element in the root node. But Can't add more than one element in the tree
Please help me solve this problem, kindly explain about the mistake that I made
#include<stdio.h>
#include<stdlib.h>
typedef struct tree
{
struct tree *left;
int data;
struct tree *right;
}node;
node *ROOT;
//////////////////////////
void *bud()
{
return (node *)malloc(sizeof(node));
}
/////////////////////
void createNode(int data, node *ptr)
{
if(ptr==NULL)
{
ptr=bud();
ptr->data=data;
ptr->left=NULL;
ptr->right=NULL;
ROOT=ptr;
ptr=NULL;
printf("DONE");
return;
}
else if(data==ptr->data)
{
printf("Duplication not possible");
return;
}
else if (data<ptr->data)
{
//ptr=ptr->left;
createNode(data,ptr->left);
}
else if (data>ptr->data)
{
//ptr=ptr->right;
createNode(data,ptr->right);
}
else
{
printf("INVALID");
}
}
//////////////////////////////////////
void search(int data,node *ptr)
{
if(ptr==NULL)
{
printf("NOT FOUND");
return;
}
else if (ptr->data==data)
{
printf("Item Found");
return;
}
else if(data<ptr->data)
{
//ptr=ptr->left;
search(data,ptr->left);
}
else if (data>ptr->data)
{
//ptr=ptr->right;
search(data,ptr->right);
}
else
{
printf("INVALID");
}
}
/////////////////////////////////
void main()
{
int ch;
ch=0;
while (ch!=6)
{
printf("\nMENU\n1. Create Tree\n2. Search\n3. Inorder\n4.
Preorder\n5. Postorder\n6. Exit\n EnterYour Choice: ");
scanf("%d",&ch);
if(ch==1)
{
int dat;
printf("\nEnter the number to be inserted: ");
scanf("%d",&dat);
createNode(dat,ROOT);
}
else if(ch==2)
{
int dat;
printf("Enter number to be searched: ");
scanf("%d",&dat);
search(dat,ROOT);
}
else if(ch==6)
{
return;
}
else
{
printf("\nEnter a valid choice\n");
}
}
}
The problem is logical error. I can't create the left or right child of the tree. Whatever I insert to the tree gets inserted to the root node.
I can't create the left or right child of the tree. Whatever I insert to the tree gets inserted to the root node.
This is happening because of this statement in your createNode():
ROOT=ptr;
Whenever you are inserting an element in the tree, you are traversing tree recursively and when you find the appropriate location to insert, you are passing it to createNode() which is NULL (either ptr->left or ptr->right) and ROOT is reassigned to ptr.
If I just make changes in your program to make work it properly, the createNode() will look like this:
void createNode(int data, node **ptr)
{
if(*ptr==NULL)
{
*ptr=bud();
(*ptr)->data=data;
(*ptr)->left=NULL;
(*ptr)->right=NULL;
printf("DONE");
return;
}
else if(data==(*ptr)->data)
{
printf("Duplication not possible");
return;
}
else if (data<(*ptr)->data)
{
createNode(data,&((*ptr)->left));
}
else if (data>(*ptr)->data)
{
createNode(data,&((*ptr)->right));
}
else
{
printf("INVALID");
}
}
And in main(), you need to do:
createNode(dat,&ROOT);
However, there is a scope of improvement in your program, for e.g. separate the node creation and insertion operation in your program. I am leaving it up to you to find the improvements and better ways of theirs implementation.
The error is in your createNode() function: you pass node *ptr and assign like this ptr=bud();. But this only modifies local variable, not pointer in parent node. Try passing node **ptr and do dereferencing inside of the function *ptr=bud();. Use & operator to derive pointer to pointer. As #H.S. mentioned ROOT=ptr; statement makes your program lose node. Besides you allocate memory and don't free it (you can't even do that, because you lose pointer to ROOT node).

Insert a node in a binary tree - Convert iterative to recursive

Repeated Question:
Recently I'm reading Data Structure(Binary Search Trees), I understand recursion very well and can trace it as well.
I used an approach which always worked for me i.e write a program with a loop, then eliminate loop and write a recursive function, the base condition will be same as loop exit condition.
But when it comes to writing one without my loop method, am getting failed.
I wasn't able to write a recursive function to insert a node in Binary Search Tree.(Though I understood it properly by referring the solution).
Kindly guide me, How to improve it?
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *left;//To store the address of the left child
struct node *right;//To store the address of the Right child
};
struct node * root;
struct node *createnewnode(int x)
{
struct node *n=(struct node *)malloc(sizeof(struct node));
n->data=x;
n->left=NULL;
n->right=NULL;
return n;
}
void Insert(int x)
{
struct node *a,*b;
struct node *temp=root;
if(root==NULL)
root=createnewnode(x);
else
{
while(1)
{
if(x<=temp->data)
{
if(temp->left!=NULL)
temp=temp->left;
else
{
a=createnewnode(x);
temp->left=a;
break;
}
}
else
{
if(temp->right!=NULL)
temp=temp->right;
else
{
a=createnewnode(x);
temp->right=a;
break;
}
}
}
}
}
int main()
{
root==NULL;//Empty Tree
Insert(15);
Insert(10);
Insert(20);
Insert(25);
return 0;
}
Edit: Sorry for not posting the code previously.
This is the code I have written for inserting a node, now how do I convert this into a recursive method?
The recursive Insert always asks the following question: can I insert a node in the current root? If not because root is not null then I have to check whether I have to recurse on the left or right subtree and call Insert recursively.
Something like the following should be enough to give you an idea on how to do it
Node* Insert(Node* root, int x) {
if (root == NULL)
return createnewnode(x);
else
if (x <= root->data)
root->left=Insert(root->left);
else
root->right=Insert(root->right);
}

Unable to print elements in binary search tree

My code is not printing the elements of binary search tree:
//x is the element to be inserted
//structure of program
typedef struct BST
{
int info;
struct BST *left;
//pointer to left node
struct BST *right;
//pointer to right node
}
bst;
//global root variable
bst *root;
void insert(int x)
{
bst *ptr,*sptr=root;
ptr=(bst*)malloc(sizeof(bst));
ptr->info=x;
if(root==NULL)
{
ptr->left=ptr->right=NULL;
root=ptr;
}
while(sptr!=NULL)
{
if(x<sptr->info)
{
sptr=sptr->left;
}
else
sptr=sptr->right;
}
sptr=ptr;
}
edit:
//following is the show function
void show()
{
bst *ptr=root;
while(ptr!=NULL)
{
//it will print untill the ptr is null
printf("%d",ptr->info);
ptr=ptr->left;
ptr=ptr->right;
}
}
Where is the value of root coming from? You're not passing in the value anywhere? Also, it is tough to help when we don't know the design of type bst.
It appears that you have the right idea. Create a node, and give it some data. If the root is null, then the new value is the root of the BST. After that you go ahead and find the first null node either in the left or right subtree of the root using the standard BST behavior. Finally, when you reach the end you go ahead and insert the last node in the proper place.
void insert(int x)
{
bst *ptr, *sptr=root; //<-- the value right here?
ptr = malloc(sizeof(bst));
ptr->info = x;
if(root == NULL)
{
ptr->left=ptr->right=NULL;
root=ptr;
}
while(sptr!=NULL)
{
if(x<sptr->info)
{
sptr=sptr->left;
}
else
sptr=sptr->right;
}
sptr=ptr; // <-- What is this line trying to do?
}
However, where did your updated tree go?
Since in C everything is passed by value, you're running into the problem where you're not seeing your updated tree after you leave this function. You need to go ahead and change the function to return a bst* type, and also maintain the root node during the entire function. Now the first line of code (*sptr = root) makes more sense! Finally, you were not setting the left and right fields of ptr to NULL. This means you were jumping over your if statements.
bst* insert(int x, bst *root)
{
bst *ptr, *sptr=root;
ptr = malloc(sizeof(bst));
ptr->left = NULL;
ptr->right = NULL;
ptr->info = x;
if(root == NULL)
{
ptr->left=ptr->right=NULL;
root=ptr;
return root;
}
while(sptr!=NULL)
{
if(x<sptr->info)
{
sptr=sptr->left;
}
else
sptr=sptr->right;
}
sptr=ptr;
return root;
}
What about the next function?
I just started looking at this one too. I am not used to the global variables in c, so I will go ahead and make two modifications. Let's make this recursive, and pass in the value of the root rather than using the global.
void show(bst *root)
{
if(root == NULL){
return;
}
printf("%d",root->info);
show(root->left);
show(root->right);
}
This will take in some value, and solve the tree recursively, and print as it reaches each node. Thus, it will print the root node (if it exists), and then print the left entire left subtree before it prints the right subtree.
Finally, looking at your main
I added the local variable root and thus you will have to remove the global variable named root outside of your main function. I also set the value of it to null so your first insert will fire correctly.
int main()
{
int i,n,x;
bst *root = NULL; //<-- I added this line of code to remove the global
puts("Enter number of elements");
scanf("%d",&x);
for(i=0;i<x;i++)
{
puts("Enter elements");
scanf("%d",&n);
root = insert(n, root);
}
show(root);
return 0;
}
I hope this helps!

Using Pointer to Pointer of Struct while adding nodes in the binary tree

I want to know the reason why do we use, pointer to pointer while inserting nodes in the binary tree.
But, While traversing the binary tree, we just refer the tree by simple pointer to the root node. But why while inserting node?
Can anyone help me in providing the reason or reference link to understand why it is pointer to pointer .
/*This program clears out all the three methods of traversal */
#include<stdio.h>
#include<stdlib.h>
/* Let us basically describe how a particular node looks in the binary tree .... Every node in the tree has three major elements , left child, right child, and and the data. */
struct TreeNode {
int data;
struct TreeNode *leftChild;
struct TreeNode *rightChild;
};
void inorder(struct TreeNode *bt);
void preorder(struct TreeNode *bt);
void postorder(struct TreeNode *bt);
int insert(struct TreeNode **bt,int num);
main()
{
int num,elements;
struct TreeNode *bt;
int i;
printf("Enter number of elements to be inserted in the tree");
scanf("%d",&num);
printf("Enter the elements to be inserted inside the tree");
for(i=0;i<num;i++)
{
scanf("%d",&elements);
insert(&bt,elements);
printf("\n");
}
printf("In Order Traversal \n");
inorder(bt);
printf("Pre Order Traversal \n");
preorder(bt);
printf("Post Order Traversal \n");
postorder(bt);
return 0;
}
int insert(struct TreeNode **bt,int num)
{
if(*bt==NULL)
{
*bt= malloc(sizeof(struct TreeNode));
(*bt)->leftChild=NULL;
(*bt)->data=num;
(*bt)->rightChild=NULL;
return;
}
else{
/* */
if(num < (*bt)->data)
{
insert(&((*bt)->leftChild),num);
}
else
{
insert(&((*bt)->rightChild),num);
}
}
return;
}
void inorder(struct TreeNode *bt){
if(bt!=NULL){
//Process the left node
inorder(bt->leftChild);
/*print the data of the parent node */
//printf(" %d ", bt->data);
/*process the right node */
inorder(bt->rightChild);
}
}
void preorder(struct TreeNode *bt){
if(bt)
{
//Process the parent node first
printf("%d",bt->data);
//Process the left node.
preorder(bt->leftChild);
//Process the right node.
preorder(bt->rightChild);
}
}
void postorder(struct TreeNode *bt){
if(bt)
{
//process the left child
postorder(bt->leftChild);
//process the right child
postorder(bt->rightChild);
//process the parent node
printf("%d",bt->data);
}
}
"I want to know the reason why do we use, pointer to pointer while inserting nodes in the binary tree. But, While traversing the binary tree, we just refer the tree by simple pointer to the root node. But why while inserting node?"
We actually don't even need the code to answer this. If you want to modify (write to) data in an external function in C, you need to have the address of the data. Just like:
main() {
int x = 2;
change_me(x);
printf("%d\n", x); // prints 2
}
void change_me(int x){
x++;
}
has no meaning. You're (in this example) getting a local copy of the vairable, any changes made to the value are only within the local scope. If you want those changes to propagate back to the calling function you need the address:
main() {
int x = 2;
change_me(&x);
printf("%d\n", x); // prints 3
}
void change_me(int* x){
(*x)++;
}
The same applies to pointers. In the example of a linked list, if I want to print the values, I need to traverse the tree and read data. I don't need to change anything so just the pointer will do. However if I want to modify the tree:
struct node{
int val;
sturct node* next;
};
main() {
struct node* head = malloc(sizeof(struct node));
head->val = 3;
insert_a_node_in_front(head);
}
insert_a_node_in_front(node * ptr) {
struct node* temp = ptr;
ptr = malloc(sizeof(struct node));
ptr->val = 5;
ptr->next = temp;
}
Well, guess what? We didn't actually just insert that node because head's value never changed. It's still pointing to the original node with a val==3. The reason is the same as before, we tried to change the value of the local copy of the parameter. If we want those changes to stick it needs the address of the original copy:
insert_a_node_in_front(&head);
}
insert_a_node_in_front(node ** ptr) {
struct node* temp = (*ptr);
(*ptr) = malloc(sizeof(struct node));
(*ptr)->val = 5;
(*ptr)->next = temp;
}
It's because of the first part of insert where it mallocs a new struct treenode. If you only passed in a struct treenode * this would look something like this:
int insert(struct TreeNode *bt,int num)
{
if(bt==NULL)
{
bt= malloc(sizeof(struct TreeNode));
(bt)->leftChild=NULL;
(bt)->data=num;
(bt)->rightChild=NULL;
return;
}
...
}
The problem with that would be that bt is local to insert so the bt in main would be unchanged. So you pass in a pointer to main's bt, which allows insert to change it.
a very good tips on using pointer is given here :
Try this basics : -
http://www.geeksforgeeks.org/how-to-write-functions-that-modify-the-head-pointer-of-a-linked-list/

Deleting the leaf nodes of a binary search tree - segmentation fault

I am trying to delete the leaf nodes in a BST which I have created non-recursively. The problem is when I am trying to delete the leaf node I hit a segmentation fault and I have no clue as to why its happening. I believe the code which I have commented is causing the problem. Is the idea of deleting that node wrong or are there any other ways of deleting any node from the BST ?
#include <stdio.h>
#include <stdlib.h>
struct BSTnode
{
int data;
struct BSTnode *left,*right,*parent;
};
typedef struct BSTnode node;
void insert(node **root,int val)
{
node *ptr,*newptr;
newptr=(node *)malloc(sizeof(node));
newptr->left=NULL;
newptr->right=NULL;
newptr->parent=NULL;
newptr->data=val;
if((*root)==NULL)
{
(*root)=newptr;
return;
}
ptr=(*root);
while(ptr!=NULL && ptr->data!=val)
{
if(ptr->data >val )
{
if(ptr->left!=NULL)
ptr=ptr->left;
else
{
ptr->left=newptr;
newptr->parent=ptr;
break;
}
}
else
{
if(ptr->right!=NULL)
ptr=ptr->right;
else
{
ptr->right=newptr;
newptr->parent=ptr;
break;
}
}
}
}
void deleteLeaf(node **root)
{
node *leafParent=NULL;
if((*root)->left!=NULL)
deleteLeaf(&((*root)->left));
if((*root)->right!=NULL)
deleteLeaf(&((*root)->right));
if((*root)->left==NULL && (*root)->right==NULL)
{
/* leafParent=(*root)->parent;
if(leafParent->left==(*root))
leafParent->left=NULL;
else
leafParent->right=NULL;
*/
free(*root);
}
}
void inorder(node *root)
{
if(root->left!=NULL)
inorder(root->left);
printf(" %d ", root->data);
if(root->right!=NULL)
inorder(root->right);
}
main()
{
node *root=NULL;
int i,n,val;
printf("\n How many elements ?");
scanf("%d",&n);
for(i=0;i<n;++i)
{
scanf("%d",&val);
insert(&root,val);
}
printf("\n Inorder traversal : ");
inorder(root);
deleteLeaf(&root);
printf("\n Inorder traversal : ");
inorder(root);
}
Indeed there are cases in the function deleteLeaf where the (commented out) leafParent is NULL, and then as soon as you dereference it with leafParent->left, it seg faults. So you need to put a check in there as follows:
leafParent=(*root)->parent;
if (leafParent)
{
if(leafParent->left==(*root))
{
leafParent->left=NULL;
}
else
{
leafParent->right=NULL;
}
}
This will prevent the seg fault, but I am not clear if the function will end up doing what you want it to do... In other words your logic might still need some tweaking to get it to just delete the leaf nodes (if that is what you are attempting to do).
I believe you are not really deleting just the leaves - you are recursively deleting the whole tree: for each node you first you delete the leaves and then check whether it is a leaf ((left == NULL) && (right == NULL)) - which it obviously is since you just deleted its descendants - and then delete it.
The first problem is, as Chris quickly pointed out, that you are not checking that leafParent can become NULL. Either check for that or set parent to itself for the root node so that you don't dereference NULL. The other (imho worse) problem is that you are not invalidating pointers once you free the memory - good habit is to set pointers to NULL as soon as you free them. If you don't do checks later on you can segfault but won't silently corrupt memory by using the pointer later on when the chunk of memory might be allocated by some other structure. You can even write a wrapper to do that for you (and it can also check for attempts to free a NULL pointer, which is actually a valid operation that just silently does nothing - at least on some platforms). In this particular case, once you finish deleting the whole tree (as that is what really happens), you still have pointer to the removed root node inside of main() - and you use it immediately.
As a nitpicking side-note, in code it is either int main(void) { ... } or int main(int argc, int **argv) { ... } not just main(). :-)

Resources