Binary Search Tree in C. - c

I am confused that what mistake i am doing. Why isn't it printing the tree in preorder, postorder and inorder. I have written my questions beside the line of code where i am confused. Plus i don't understand how to relate to structs.
#include <stdio.h>
#include<stdlib.h>
typedef struct BST_{
int data;
struct BST_ *lchild, *rchild, *parent;
}BST;
typedef struct BiTree_{
int size;
BST *root; // is it possible to relate this root with the pointer parent of type BST? i yes then how?
}BiTree;;
BST *temp;
BST *createNode(int data){
BST *new_ele;
new_ele=(BST*)malloc(sizeof(BST));
new_ele->data=data;
new_ele->lchild=NULL;
new_ele->rchild=NULL;
new_ele->parent=NULL;
return new_ele;
}
void insertNode(BST *temp,BST *r,int data){
if(temp==NULL){
temp=createNode(data);
}
else if(temp->data >= r->data){
if(r->rchild==NULL){
r->rchild=temp;
}
else{
insertNode(r->rchild,temp,data);
}
}
else if(temp->data <= r->data){
if(r->lchild==NULL){
r->lchild=temp;
}
else{
insertNode(r->lchild,temp,data);
}
}
// return r->data; //why cann't i do this?
}
void preorder(BST *r){
if(r!=NULL){
printf("%d",r->data);
preorder(r->lchild);
preorder(r->rchild);
}
}
void inorder(BST *c){
if(c!=NULL){
inorder(c->lchild);
printf("%d",c->data);
inorder(c->rchild);
}
}
void postorder(BST *r){
if(r!=NULL){
postorder(r->lchild);
postorder(r->rchild);
printf("%d",r->data);
}
}
void delet(BST *r){
if(r!=NULL){
free(r);
}
}
void main(){
BST *new_node,*r=NULL;
BiTree *search;
search=malloc(sizeof(BiTree));
search->root=NULL;
search->size=0;
int i,a,n,data;
printf("Enter the number of element to be inserted\n");
scanf("%d",&n);
printf("Enter the data\n");
for(i=0;i<n;i++){
scanf("%d",&data);
insertNode(temp,r,data);
// printf("Enter the data %d\n",r->data); // unable to print this
search->size++;
}
printf("size is %d\n",search->size);
preorder(r);// why cann't i print the data of r. r is the root of the tree.
postorder(r);
inorder(r);
delet(r);
}

// is it possible to relate this root with the pointer parent of type BST? i yes then how?*
Please rephrase this question
// return r->data; //why cann't i do this?
The signature of the function void insertNode(BST *temp,BST *r,int data){ is saying that nothing should be returned. Change this
printf("Enter the data %d\n",r->data); // unable to print this
In the function r is initialised to NULL and nothing in the function changes this
why cann't i print the data of r. r is the root of the tree.
See the point above

temp is not set to NULL, and I think if its not NULL, it is going to have garbage in it.
With this your insertNode() function will not allocate memory and all the code inside this function is entirely dependent on the garbage value of temp.

Related

Why the address returned by the create function is not same as root for the first node

Below is my code for the BST :
insert works fine but search doesnt
typedef struct tree_node{
struct tree_node* parent;
struct tree_node* left;
struct tree_node* right;
int x;
}tree_node;
tree_node *strt=NULL;
tree_node *traverse;
tree_node* create(int info){
tree_node *temp=NULL;
temp=(tree_node*)malloc(sizeof(tree_node));
temp->parent=NULL;
temp->left=NULL;
temp->right=NULL;
temp->x=info;
return temp;
}
tree_node* insert(tree_node *root, int a){
/* here i am printing the address of the node which must be same as the root for the first node */
if(root==NULL){
printf("%d ",create(a));
return create(a);
}
else if(a <= root->x)
return insert(root->left,a);
else
return insert(root->right,a);
return root;
}
tree_node* search_ele(tree_node *root,int info){
if(root==NULL || root->x==info)
return root ;
if(info < root->x)
return search_ele(root->left,info);
else
return search_ele(root->right,info);
}
void display_inorder(tree_node *root){
if(root==NULL)
return;
display_inorder(root->left);
printf("%d ",root->x);
display_inorder(root->right);
}
void main(){
int element;
tree_node *search_element;
while(1){
char ch;
int num;
printf("\nWant to enter a node..??\n\n");
scanf(" %c",&ch);
if(ch=='n'||ch=='N')
break;
else{
printf("Enter the number \n");
scanf("%d",&num);
if(strt==NULL)
printf("Tree is empty...entering first node...!!!\n");
strt=insert(strt,num);
printf("%d",strt);
}
}
printf("Enter the element u want to search\n");
scanf("%d ",&element);
if(search_ele(strt,element)==NULL)
printf("no such element\n");
else
printf("element found\n");
display_inorder(strt);
}
The output displays :
Want to enter a node ?
y
Enter the number
6
Tree is empty...entering first node...!!!
5279480 5279504 (why are these different??)
You print the result of calling create, and then call create again for the return value, thus creating a second node.
First the problems with your BST Algorithm: Your node creation algorithm never attaches new nodes to a parent. Create() sets node->parent to NULL and your insert() never updates the parent variable to root. Additionally, you're never setting the new left/right fields of your new node's parent
Change
return create(a)
to
tree_node * new_node = create(a);
new_node->parent=root;
new_node->parent->left/right=new_node; //include some way to distinguish whether you went left or right in the previous recursive call
return new_node
Now for your address question, you call create() twice, which (think procedurally) results in two malloc() calls, and thus two addresses.

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!

Creating a binary tree but it doesn't work — tree is always null

I am creating a code to insert the elements in tree, but tinsert function does not insert; what is wrong with my code? I have checked many times but tree is always NULL.
The code has only 2 functions: one to insert, and second to show it in preorder.
#include<stdio.h>
#include<stdlib.h>
struct btree {
int val;
struct btree *left;
struct btree *right;
};
static int c=0;
typedef struct btree node;
void tinsert( node *n,int a)
{
c++;
printf("%d\n",c);
if(n==NULL)
{
n=(node *)malloc(sizeof(node));
n->left=NULL;
n->right=NULL;
n->val=a;
//printf("adding root %d\n",n->val);
//n=temp;
}
else if(a>=(n->val))
tinsert(n->right,a);
else
tinsert(n->left,a);
return ;
}
void preorder_display(node *n)
{
if(n!=NULL)
{
printf("%d\n",n->val);
preorder_display(n->left);
preorder_display(n->right);
}
else
printf("tree is null\n");
}
int main()
{
//int N;
//int num[100];
//int i;
node *ntree=NULL;
tinsert(ntree,4);
tinsert(ntree,6);
tinsert(ntree,8);
tinsert(ntree,1);
printf("tree is \n");
preorder_display(ntree);
return 0;
}
tinsert works on a local copy of your ntree, it doesn't change the one in your main. You can fix it by passing a pointer to it (i.e.: double pointer, pointer to a pointer).
So your tinsert will look like this:
void tinsert( node **n,int a)
And in your main you'll call it like this:
tinsert(&ntree,4);
Of course, you'll need to adjust the code in tinsert to de-reference the pointer and access it correctly.
Or allocate the root node in your main.
you pass your root node ntree to tinsert function by value, so when when the function is done you will stay with original value of ntree which is NULL.
You better rewrite your function, so you will pass pointer to pointer
void tinsert( node **n,int a)
//and invocation is like that :
tinsert(&ntree,4);
when you pass ntree from main to tinsert function,
new copy is created to your node*n;
One way is to make use of pointer to pointer
Or second solution is here:
Here is a solution:
#include<stdio.h>
#include<stdlib.h>
struct btree{
int val;
struct btree *left;
struct btree *right;
};
static int c=0;
typedef struct btree node;
node* tinsert( node *n,int a)
{
c++;
printf("%d\n",c);
if(n==NULL)
{
n=(node *)malloc(sizeof(node));
n->left=NULL;
n->right=NULL;
n->val=a;
//printf("adding root %d\n",n->val);
//n=temp;
}
else if(a>=(n->val))
tinsert(n->right,a);
else
tinsert(n->left,a);
return n;
}
void preorder_display(node *n)
{
if(n!=NULL)
{
printf("%d\n",n->val);
preorder_display(n->left);
preorder_display(n->right);
}
else
printf("tree is null\n");
}
int main()
{
//int N;
//int num[100];
//int i;
node *ntree=NULL;
ntree=tinsert(ntree,4);
ntree=tinsert(ntree,6);
ntree=tinsert(ntree,8);
ntree=tinsert(ntree,1);
printf("tree is \n");
preorder_display(ntree);
return 0;
}
C supports the pass by value only. However, this does not prevent you from modifying the value of a variable from another function, because you can always refer to a variable using it's memory; and in C it's done through pointers, an abstraction representing a memory location.
When you pass a value to the function, the value of the actual parameter is copied to the value of formal parameter. Note that a pointer's value is the address it points to. So, this value is copied into the formal parameter. So the new pointer inside the function points to the exact same location your original variable. You can deference the pointer anytime to manipulate it's value.
Here, you are required to manipulate a pointer. So you pass a pointer-to-pointer to the function:
tinsert(&ntree,4);
In your function, you deference it to get your original pointer; like the following:
void tinsert(node **n, int a)
{
//...
*n = malloc(sizeof(node));
//...
}

Binary search tree insertion - root always null

I have ds code for inserting values in a binary search tree using recursion. The problem is that the root always remains null.
Upon execution, the 1st printf() prints 10 but the 2nd printf (after insertRec(10)) does not print anything as root is null.
#include<stdio.h>
#include<malloc.h>
struct llist
{
int data;
struct llist *left;
struct llist *right;
};
typedef struct llist node;
void insertRec(node *r, int num)
{
if(r==NULL)
{
r=(node*)malloc(sizeof(node));
r->data=num;
r->left=NULL;
r->right=NULL; printf("%d ",r->data); //1st printf
}
else
{
if(num < r->data)
insertRec(r->left, num);
else
insertRec(r->right, num);
}
}
void display(node *x)
{
if(x != NULL)
{
display(x->left);
printf("%d-->",x->data);
display(x->right);
}
else
return;
}
int main()
{
node *root=NULL;
insertRec(root,10);
if(root !=NULL)
printf("\ndata=%d",root->data); //2nd printf
insertRec(root,5);
insertRec(root,15);
insertRec(root,3);
insertRec(root,18);
display(root);
getch();
}
You are passing root as value so changes made to root in insert function doesn't reflect at main function, hence root remains NULL in main function. To rectify your code, you need to pass Pointer to pointer. Pass address of root to reflect change in main function.
void insertRec(node *r, int num)
should be coded like:
void insertRec(node **r, int num)
{
if(*r==NULL)
{
*r= malloc(sizeof(node));
(*r)->data=num;
//
and use *root inside insert function.
And call it as insertRec(&root, 10); from main.
Additionally, if you allocates memory dynamically then you should free allocated memory using free explicitly.
One more thing learn Indenting C Programs.

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/

Resources