i have written a simple code to create and insert elements into a binary search tree, when i write the code in the following manner, the chaining doesn't seem to happen, can anybody help me understand what exactly is happening in the insert function ? I know the code to insert elements into a binary search tree, just curious to know why this one doesn't work.
#include <stdio.h>
#include<stdlib.h>
struct node {
struct node *left;
struct node* right;
int element;
};
void insert(struct node *node,int x) {
if(node==NULL) {
node=(struct node *)malloc(sizeof(struct node));
node->element=x;
node->left=NULL;
node->right=NULL;
} else {
if(x<node->element) {
insert(node->left,x);}
else {
insert(node->right,x);
}
}
}
void inorder(struct node *base) {
if(base!=NULL) {
inorder(base->left);
printf("%d ",base->element);
inorder(base->right);
}
}
int main(int argc, char *argv[]) {
struct node *base;
base=(struct node *)malloc(sizeof(struct node));
base->element=1;
base->left=NULL;
base->right=NULL;
insert(base,25);
insert(base,30);
inorder(base);
return 0;
}
if the insert function is written this way, it works but still doesn't work for creation of the first node of the binary search tree, confused :/
void insert2(struct node *node,int x) {
if(node==NULL) {
node=(struct node *)malloc(sizeof(struct node));
node->element=x;
node->left=NULL;
node->right=NULL;
} else {
if(x<node->element) {
if(node->left==NULL) {
node->left=(struct node *)malloc(sizeof(struct node));
node->left->element=x;
node->left->left=NULL;
node->left->right=NULL;
} else {
insert2(node->left,x);
}
} else {
if(node->right==NULL) {
node->right=(struct node *)malloc(sizeof(struct node));
node->right->element=x;
node->right->left=NULL;
node->right->right=NULL;
} else {
insert2(node->right,x);
}
}
}
}
When you pass a value to a function in C, you're using pass-by-value. What that means is the value gets copied into another variable which becomes local to the function.
void change(struct node *n) {
n = 42;
}
int main(void) {
change(NULL); // change can't change the value of NULL, can it?
}
Now take a look at your insert function... Suppose I call insert(NULL,42);, do you think insert is trying to change NULL? Or is it trying to change some local variable, which your main function can't see?
You know what needs to be done already... Either make your insert function use an extra level of pointer indirection as you've suggested in your comments, or return the root node from insert so that you can propagate the changes made by insert into the data structure stored in main (using the assignment = operator).
C is pass-by-value. When you pass something into a function's parameter, the function makes a copy of it. So when you pass a struct node pointer into the insert function, C makes a copy of that pointer.
What you did in main is first you made a struct node* base:
base --> struct node.
When you call insert(base, 25), C makes a copy of base. So now in your memory you have something like this:
basecpy ---> [struct node] <--- base
So in your insert, you are essentially doing
if(basecpy==NULL)
{basecpy=(struct node *)malloc(sizeof(struct node));
basecpy->element=x;
basecpy->left=NULL;
basecpy->right=NULL;}
Which does not change base in anyway at all - it just changes basecpy.
This can be solved by using double pointers:
void insert(struct node **node, int x) {
if (*node == NULL) {
*node = malloc(sizeof(*node));
(*node)->element=x;
(*node)->left=NULL;
(*node)->right=NULL;
} else {
if (x < (*node)->element) {
insert(&((*node)->left), x);
} else {
insert(&((*node)->right), x);
}
}
}
And then to use it, pass in the address of base.
insert(&base, 25);
Pointers can be tricky :)
ideone
Related
There is a insert function which inserts in the tree recursively and display function for displaying the output.
the display() function is not displaying anything? Is there any error which I'm missing out?
please help
#include <stdio.h>
#include<stdlib.h>
typedef struct node
{ int val;
struct node *left;
struct node *right;
} node;
node *root=NULL;
void insert(node *root1,int value)
{
if(root==NULL)
{
node *temp=(node*)malloc(sizeof(node));
temp->val=value;
temp->left=NULL;
temp->right=NULL;
root=temp;
root1=root;
return;
}
if(root1==NULL && root!=NULL)
{
node *temp=(node*)malloc(sizeof(node));
temp->val=value;
temp->left=NULL;
temp->right=NULL;
root1=temp;
return;
}
if(root1->val >value)
{
insert(root1->left, value);
}
else
{
insert(root1->right, value);
}
return;
}
void display(node *root1)
{
if(root1==NULL)
{
return;
}
while(root1 !=NULL)
{
printf("%d\n", root1->val);
display(root1->left);
display(root1->right);
return;
}
}
int main()
{
insert(root,4);
insert(root,12);
insert(root,2);
insert(root,55);
display(root);
return 0;
}
Actually I'm new to programming and trying to implement trees. New suggestions are also welcome! Thank you
//EDIT
void sayHi(int* nums){
printf("hello");
printf("my address is %d \n",nums);
printf("val of nums[2] is%d\n", nums[2]);
nums[2]=30;
}
void someFunct(int* nums, int numsSize){
nums[2]=50;
sayHi(nums);
printf("address is %d\n",nums);
printf("val of nums[2] is%d\n", nums[2]);
}
input i.e., nums =[0,0,0,0,0]
output for above code is
hellomy address is 16
val of arr[2] is50
address is 16
val of arr[2] is30
Here we are passing sayHi(nums)?and it still works? Address of nums is same in someFunct and sayHi?
Does passing arg like someFunct(&ptr) only happens for structures?
Method 1
In this method the root pointer is declared as a local variable in main, and the address of the pointer is passed to the insert function. This allows the insert function to change the value of root in main.
The downside of this method is that it involves some of the nastiest syntax in the C language, with *s and &s sprinkled everywhere, along with an inordinate number of mandatory parentheses.
void insert(node **root, int value)
{
if (*root == NULL)
{
node *temp=malloc(sizeof(node));
temp->val=value;
temp->left=NULL;
temp->right=NULL;
*root = temp;
}
else
{
if((*root)->val > value)
insert(&(*root)->left, value);
else
insert(&(*root)->right, value);
}
}
int main(void)
{
node *root=NULL;
insert(&root,4);
insert(&root,12);
insert(&root,2);
insert(&root,55);
display(root);
}
Method 2
Similar to method 1, this method also passes the address of the root pointer to the insert function, but to avoid some of the nasty syntax imposed by pointers-to-pointers, a local pointer item is used to access structure contents. This eliminates most of the *s and parentheses that were needed in method 1.
The downside of this method is that there are still &s sprinkled throughout the code, and it's easy to forget the line *root = temp; which updates the caller's pointer.
void insert(node **root, int value)
{
node *item = *root;
if (item == NULL)
{
node *temp=malloc(sizeof(node));
temp->val=value;
temp->left=NULL;
temp->right=NULL;
*root = temp;
}
else
{
if(item->val > value)
insert(&item->left, value);
else
insert(&item->right, value);
}
}
int main(void)
{
node *root=NULL;
insert(&root,4);
insert(&root,12);
insert(&root,2);
insert(&root,55);
display(root);
}
Method 3
In this method, we return the new root pointer from the insert function. Thus, the first function parameter can be a simple pointer. This eliminates the nasty syntax found in method 1. There are fewer *s, absolutely no &s, and no inordinate parentheses.
The downside to this method is that the return value from the function needs to be assigned to the appropriate pointer. That results in a couple of assignments in the insert function (at the recursive calls), as well as assignments in main.
node *insert(node *root, int value)
{
if (root == NULL)
{
root=malloc(sizeof(node));
root->val=value;
root->left=NULL;
root->right=NULL;
}
else
{
if(root->val > value)
root->left = insert(root->left, value);
else
root->right = insert(root->right, value);
}
return root;
}
int main(void)
{
node *root=NULL;
root = insert(root,4);
root = insert(root,12);
root = insert(root,2);
root = insert(root,55);
display(root);
}
Boilerplate
Here's the code that when combined with the insert and main functions from any method above gives a complete set of code that can be compiled and run.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{ int val;
struct node *left;
struct node *right;
} node;
void display(node *root)
{
if(root != NULL)
{
printf("%d\n", root->val);
display(root->left);
display(root->right);
}
}
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);
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct node_{
int val;
struct node_ *left;
struct node_ *right;
}node;
node* insert(node* root,int val);
void inorder(node* root);
int main(void)
{
int i;
int item;
node* root = NULL;
srand(time(NULL));
for( i = 0; i < 10; i++)
{
item = rand()%15;
insert(root,item);
}
inorder(root);
return 0;
}
node* insert(node* root,int val)
{
if(root == NULL)
{
root = malloc(sizeof(node));
if(root!= NULL)
{
(root)->val = val;
(root)->left = NULL;
(root)->right = NULL;
}
else
printf("%d not inserted. No memory available.\n",val);
}
else
{
if(val < (root)->val)
{
insert((root->left),val);
}
if(val>root->val)
{
insert(((root)->right),val);
}
}
}
void inorder(node* root)
{
printf("%p",root);
if(root != NULL)
{
inorder(root->left);
printf("%3d",root->val);
inorder(root->right);
}
}
I am trying to create a binary tree and print out the values in order. However when I run this code the printf of the address prints out nil obviously meaning that my tree is empty so the printf and recursion below does not run. I cannot figure out where I went wrong, any suggestions or answers would be appreciated because I can't figure out why the root would be null after calling all of those inserts in main.
You pass root as a parameter to insert() (which says it is going to return something but doesn't). Inside insert you malloc your node and assign it to the local variable root. Nothing you ever do makes it out of the insert function.
Try returning something from insert, or using a global root.
As #JoshuaByer hints in the comments below, another approach is to make your insert method "pass by reference" so it can effectively modify what was passed to it.
void insert(node** rootp,int val)
{
if(*rootp == NULL)
{
*rootp = malloc(sizeof(node));
}
/* and so on */
If you don't understand what this is saying, google "Pass by reference in C" and I'm positive you'll get some good information.
In main() after declaring and initializing root (node* root = NULL;) you're never assigning it. In order to fix you should probably change the lin insert(root,item); to root = insert(root,item);.
Also note that although insert is defined as returning node * it does not return any value.
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/
I would like to get some help with the following question.
I have a struct Node and I want to change it's insides using some method.
and I want to print the content of the changed struct inside my main method.
how do I get the struct changed and see the changed value in my main without returning the node as a return value.
I guess it might be solved with passing the struct Node as a pointer and then editing it.
what is the right way to do so?
for example:
typedef struct Node{
struct Node * right;
struct Node * left;
void * data;
}Node;
void insert(void * element, Node* root){
if(root==NULL){
root=(Node*)malloc(sizeof(Node));
root->data=element;
}
}
int main(){
Node a;
int b=8;
insert(&b,&a);
printf("%d",*(int*)a.data);
return 0;
}
printf doesn't print 8 it prints 1 (i guess some garbage)
It sounds like you are trying to do the following
Create a struct in one method, say main
Pass it to a second method, say example
Have example modify the struct and have the results visible in main
If so then the way to do this in C is by passing the struct as a pointer to example.
struct Node {
int data;
struct Node* pNext;
};
void example(struct Node* pNode) {
pNode->data = 42;
pNode->pNext = NULL;
}
int main() {
struct Node n;
example(&n);
printf("%d\n", n.data);
}
EDIT
Responding to the updated question.
To see the result of a modification of a Node you must pass a Node*. And accordingly to see the result of a Node* modification you need to pass a Node**. Essentially you need to pass one more level of indirection than the value you want to mutate / return.
void insert(void* element, Node** ppRoot){
if (NULL == *ppRoot) {
Node* pTemp = malloc(sizeof(Node));
pTemp->data = element;
*ppRoot = pTemp;
}
}