Using a Binary Tree - c

#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.

Related

This is the code for inserting/creating a binary tree? but the display() function is not displaying anything? what am I missing?

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);
}
}

BINARY SEARCH TREE creation

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

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.

binary search tree pointer problem

I tried to implement a binary search tree for the purpose of (re-)learning C. The problem is that the this current = new; does not work as desired because the tree.root is still a null pointer after adding two nodes. What's wrong with that?
#include <stdlib.h>
#include <stdio.h>
typedef struct BinaryNode {
int key;
double value;
struct BinaryNode *left;
struct BinaryNode *right;
} BinaryNode;
typedef struct BinaryTree {
struct BinaryNode *root;
} BinaryTree;
static void binary_tree_insert_recursive(BinaryNode *current, BinaryNode *new) {
if (current == NULL || current->key == new->key) {
current = new;
} else if (current->key > new->key) {
binary_tree_insert_recursive(current->left, new);
} else if (current->key < new->key) {
binary_tree_insert_recursive(current->right, new);
}
}
void binary_tree_insert(BinaryTree *tree, int key, double value) {
BinaryNode *new = (BinaryNode *) malloc(sizeof(BinaryNode));
new->key = key;
new->value = value;
binary_tree_insert_recursive(tree->root, new);
}
int main(void) {
BinaryTree tree;
binary_tree_insert(&tree, 5, 123);
binary_tree_insert(&tree, 10, 123);
printf("%p\n", tree.root);
return 0;
}
Thank you!
I believe the problem with current = new; is that you are changing your local copy of current. After the function is done, this modification is not visible.
I suspect you want something like:
static void binary_tree_insert_recursive(BinaryNode **current, BinaryNode **new)
{
if (*current == NULL || (*current)->key == (*new)->key) {
*current = *new;
/* ... */
Well explained in the C FAQ.
current is a pointer to a node. When you pass it to binary_tree_insert_recursive from binary_tree_insert the value of the pointer is passed. So although it is changed inside the called function, the change is not reflected in the calling function. You need to modify the function to take the address of the pointer you wish to change:
static void binary_tree_insert_recursive(BinaryNode **current, BinaryNode *new)
{
if (*current == NULL || (*current)->key == new->key) {
*current = new;
all that current = new does is make it so that the variable current points at the thing that new is pointing at. No copying takes place, and the function has no effect on that codepath.
new is a keyword. Choose a different variable name.

Can anyone help me find why this C program work on VS2005 but not on DEV-C++

I have a C program for an exercise and it has a strange issue
The program runs just fine on VS 2005 but it crashes on DEV-C++ and the problem that the problem is that the exercise is always evaluated against DEV-C++
The program is about inserting nodes to a BST and this is where the problem lies...
Well i would really appreciate some help.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct tree_node
{
int value;
int weight;
struct tree_node *left;
struct tree_node *right;
} TREE_NODE;
TREE_NODE *create_tree(int list[], int size);
TREE_NODE *search_pos_to_insert(TREE_NODE *root, int value, int *left_or_right);
// this is the problematic function */
void inorder(TREE_NODE *root); /* Inorder Traversing */
TREE_NODE *temp;
int main()
{
TREE_NODE *root; /* Pointer to the root of the BST */
int values[] = {10, 5, 3, 4, 1, 9, 6, 7, 8, 2}; /* Values for BST */
int size = 10, tree_weight;
root = create_tree(values, 10);
printf("\n");
inorder(root); /* Inorder BST*/
system("PAUSE");
}
TREE_NODE *search_pos_to_insert(TREE_NODE *root, int value, int *left_or_right)
{
if(root !=NULL)
{
temp = root;
if(value >root->value)
{
*left_or_right=1;
*search_pos_to_insert(root->right, value, left_or_right);
}
else
{
*left_or_right=0;
*search_pos_to_insert(root->left, value, left_or_right);
}
}
else
return temp;/* THIS IS THE PROBLEM (1) */
}
TREE_NODE *create_tree(int list[], int size)
{
TREE_NODE *new_node_pntr, *insert_point, *root = NULL;
int i, left_or_right;
/* First Value of the Array is the root of the BST */
new_node_pntr = (TREE_NODE *) malloc(sizeof(TREE_NODE));
new_node_pntr->value = list[0];
new_node_pntr->weight = 0;
new_node_pntr->left = NULL;
new_node_pntr->right = NULL;
root = new_node_pntr;
/* Now the rest of the arrat. */
for (i = 1; i < size; i++)
{
/* THIS IS THE PROBLEM (2) */
insert_point = search_pos_to_insert(root, list[i], &left_or_right);
/* insert_point just won't get the return from temp */
new_node_pntr = (TREE_NODE *) malloc(sizeof(TREE_NODE));
new_node_pntr->value = list[i];
new_node_pntr->weight = 0;
new_node_pntr->left = NULL;
new_node_pntr->right = NULL;
if (left_or_right == 0)
insert_point->left = new_node_pntr;
else
insert_point->right = new_node_pntr;
}
return(root);
}
void inorder(TREE_NODE *root)
{
if (root == NULL)
return;
inorder(root->left);
printf("Value: %d, Weight: %d.\n", root->value, root->weight);
inorder(root->right);
}
Your search_pos_to_insert isn't returning anything in the first section, where root is not NULL. It is recursively calling the function, but not gathering the result. You need to return whatever your recursive calls return to ensure correctness.
You should change the calls
*search_pos_to_insert(root->right, value, left_or_right);
...
*search_pos_to_insert(root->left, value, left_or_right);
to
return search_pos_to_insert(root->right, value, left_or_right);
...
return search_pos_to_insert(root->left, value, left_or_right);
While I haven't delved deep into many issues, are you sure your use of "temp" as a global is correct here? Should it not be local to the search function, so the function is reentrant?
In your function TREE_NODE *search_pos_to_insert() you have code pathes, that don't return a value. Your compiler should issue a warning about it.
The line:
return temp;/* THIS IS THE PROBLEM (1) */
is reached only if the if(root != NULL) evaluates to true.
Replace the recursive calls with:
return search_pos_to_insert(root->right, value, left_or_right);
return search_pos_to_insert(root->left, value, left_or_right);
to make it work.
Frank your the man ..
In some moment i thought that maybe i could return the function itself but i was almost sure it wouldn't work and also i took a different road (to left_or_right) and i was completely lost
Well u saved from a lot of anger and u really saved my day(probably a lot more)

Resources