pointer problem in implementing Tree in C - c

I am implementing an avl tree for my assignment.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
struct TreeNode {
char *item;
struct TreeNode *left;
struct TreeNode *right;
signed char balance;
};
typedef struct TreeNode Node;
void _print_avl (Node *, int , const char *);
Node * get_new_node (char *);
int avl_insert(Node *, char *);
void print_avl (Node *);
void avl_swr(Node*);
int main (int argc, char *argv[])
{
Node *root = get_new_node("thura");
avl_insert(root, "thur2");
print_avl(root);
avl_insert(root, "thur1");
return 0;
}
int avl_insert(Node *root, char *item)
{
assert(root);
if( strcmp(item, root->item) < 0) {
if(!root->left) {
root->left = get_new_node(item);
if(--(root->balance)) return 1;
return 0;
} else {
if(avl_insert(root->left, item)) {
if( root->balance-- < 0) {
avl_swr(root); //Rotate the node right.
print_avl(root); //Here, the tree is corrupted.
return 0;
}
return 1;
}
}
} else {
if(!root->right) {
root->right = get_new_node(item);
if(++(root->balance)) return 1;
return 0;
}
else {
if(avl_insert(root->right, item)) {
root->balance++;
return 1;
}
}
}
return 0;
}
void avl_swr(Node* root)
{
Node *node = root;
root = node->left;
node->left = NULL;
node->balance = 0;
root->right = node;
root->balance++;
print_avl(root); // It is working fine here.
}
Node * get_new_node (char *item) {
Node * node = (Node *)malloc(sizeof(Node));
node->item = item;
node->left = NULL;
node->right = NULL;
node->balance = 0;
return node;
}
void print_avl (Node *node)
{
_print_avl(node, 0, "\t\t");
}
void _print_avl (Node *node, int depth, const char *delim)
{
if(!node)
return;
int i = 0;
while(i++ < depth) printf("%s", delim);
printf("--> %s:%d\n", node->item, node->balance);
depth++;
if(node->left)
_print_avl (node->left, depth, delim);
if(node->right)
_print_avl (node->right, depth, delim);
}
The problem is when I rotate the tree, using avl_swr (), it is successfully rotated according to the print_avl (), but when the function returns to the caller, the tree is corrupted. Any ideas?

The problem with avl_swr() is related to the function signature: void avl_swr(Node* root) and the assignment: root = node->left;
The root pointer is not being updated when the function returns (only a local copy within the function is being updated). The signature should be: void avl_swr(Node** root) in order to have the desired result.

The copy of the pointer is updated. You need to pass in a pointer to a pointer in your rotate function.

That's because the root variable in avl_insert does not change in avl_swr. When you pass it to avl_swr, a copy of the pointer is made. You change this pointer.
Change the calls to root = avl_swr(...) and have avl_swr return the root.

not 100% sure, but I do see one problem. In avl_swr() you change root to left subtree. So when you print out in avl_swr() you'll have root = "thur2". But when you return to avl_insert(), root there is unchanged, still pointing to "thura", which now has no children. So when you print that root it shows no children. Perhaps that's what you mean by corrupted?
The solution is obviously to change the "root" in avl_insert(). You can do this by having avl_swr return the new root value, or by changing the parameter from "Node* root" to "Node** root" so that change in avl_swr is "passed back" to avl_insert

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

Breakpoint triggered when freeing a pointer

I'm writing a binary search tree for a class and I probably am doing something wrong but it's beyond my skill to determine what.
Here's the node structure:
typedef struct Node {
int value;
struct Node *left;
struct Node *right;
} Node, *NodePtr;
Here's my create node function:
NodePtr nodeCreate(int value) {
NodePtr node_new = 0;
node_new = (NodePtr) malloc(sizeof node_new);
node_new->value = value;
node_new->left = 0;
node_new->right = 0;
return node_new;
}
And my destroy the whole tree function:
void treeDestroy(NodePtr root) {
if (!root) { return; }
treeDestroy(root->left);
treeDestroy(root->right);
free(root); // HERE IS WHERE MY BREAKPOINT TRIGGERS
root = 0;
}
Finally here's what my main looks like:
int main(int argc, char *argv[]) {
NodePtr tree_root = 0;
tree_root = nodeCreate(2);
tree_root->left = nodeCreate(1);
tree_root->right = nodeCreate(3);
treePrint(tree_root);
treeDestroy(tree_root);
return 0;
}
Can anyone help me find what's wrong there?
node_new = (NodePtr) malloc(sizeof node_new);
should be
node_new = malloc(sizeof *node_new);
sizeof node_new is size of pointer where as sizeof *node_new is size of object which pointer is pointing.

Why i can't add my tree an element without returnnig the pointer of root?

here's my code , i don't understand the way of these pointers and & works in here.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef struct node {
int x;
struct node * left;
struct node * right;
} node;
void add_Element(node **,int);
node * getNewNode();
void main(){
node * root = NULL;
add_Element(&root,4687);
inorder_tra_recursive(root);
if(root == NULL) printf("still Nulll\n");
else printf("not null , working\n");
}
node * getNewNode(){
node * newNode = (node*)malloc(sizeof(node));
newNode->left = NULL;
newNode->right = NULL;
newNode->x = 0;
return newNode;
}
void add_Element(node ** root,int data){
*root = getNewNode();
(*root)->x = data;
// I did not write all function !! this is just a prototype and this is working
}
void inorder_tra_recursive(node * root){// looking for elements to print !
if(root==NULL)
return ;
inorder_tra_recursive(root->left);
printf("----%d----\n", root->x);
inorder_tra_recursive(root->right);
}
This is my code and here's the thing that i don't understand when i change my add_Element function to this.
void add_Element(node * root,int data){
if(root==NULL){
root = getNewNode();
root->x = data;
}else{
if(root->x <= data)
add_Element(root->right,data);
else
add_Element(root->left,data);
}
}
It doesn't add element to the tree . but if i do it like this
node * add_Element(node * root,int data){
if(root==NULL){
root = getNewNode();
root->x = data;
return root;
}else{
if(root->x <= data)
root->right = add_Element(root->right,data);
else
root->right = add_Element(root->left,data);
}
return root;
}
It works but what's the difference here why i have to return root to get results.
void main(){
node * root = NULL;
root = add_Element(root,48464);//random number
}
i can use it like this last one but i have to learn what causing this difference .
(difference: &root to node ** root // not have to return root , works !
root to node * root // have to return root otherwise not working)
Until this day i thought this 2 way were the same but apparently it's not . So , please help me , i'm going crazy over here :D . Anyhelp will be appreciated , thanks
Don't you mean this?
void add_Element(node ** root,int data){
if(*root==NULL){
*root = getNewNode();
(*root)->x = data;
}else{
if((*root)->x <= data)
add_Element(&(*root)->right,data);
else
add_Element(&(*root)->left,data);
}
}
In your first example, you are passing a pointer variable by reference (passing &root to the node ** root parameter). In the second, you are not (passing only the pointer value root, so the pointer variable root itself cannot be changed), so the new node object is lost - unless you return it, like you ended up having to do.
oh well , i always thought it was like this ,for exp:
#include
void main(){
int Arr[50];
random(Arr,50);
printf("%d", Arr[25]);
}
void random(int * Arr,int size){
int i;
for(i=0;i<size;i++)
Arr[i] = i+1;
}
** so here i'm passing a pointer by reference but when when it's a pointer what i'm passing , i have to use "&" to pass it by reference .
i believe my exp was correct , if it's not there's still some part that i'm missing**

Segmentation error while inserting into binary tree

I cannot figure out how to run this correctly, gives segmentation error. A piece of code is below. Can you look at head too , i am not sure if it is right way of initialising head to null in another file , it is run as follows :
Table tb ;
tb= initialise_table (table_size);
tb = insert(text_words,tb);
//these 3 typedef declarations are in a "some.h" file
typedef struct node * tree_ptr;
typedef char* Key_Type;
typedef struct table* Table;
struct node {
Key_Type element;
tree_ptr left;
tree_ptr right;
};
struct table {
tree_ptr head;
};
Table init_table() {
Table head = NULL;
}
Table insert(Key_Type key ,Table temp ) {
tree_ptr t = (tree_ptr)malloc(sizeof(tree_ptr));
t->element = key;
// t->left = t->right = NULL;
if (temp->head==NULL) {
temp = (Table)malloc (sizeof (Table));
temp->head = t;
printf("empty tree ");
}
else {
temp = insert(t->element,temp);
printf("inserted into ");
}
return temp;
printf("wowo!");
}
The primary issue is in the code which, you say, is used to invoke the functions:
Table tb;
tb = insert(text_words, tb);
You have an uninitialized pointer, tb, which you pass to the function. Inside the function, you have:
Table insert(Key_Type key, Table temp)
{
tree_ptr t = (tree_ptr)malloc(sizeof(*t)); // Fixed size
t->element = key;
// t->left = t->right = NULL;
if (temp->head==NULL)
{
You're therefore accessing (dereferencing) the undefined pointer, and your program is crashing.
You should, I assume, be initializing your table with table_init(), but that function is actually no help whatsoever. It defines and initializes a local variable, but doesn't return anything even though it promises to do so.
Please see Is it a good idea to typedef pointers? The short answer is 'No, it usually isn't a good idea'.
You still have problems even if you fix the calling code like this (a necessary but not sufficient step):
Table tb = NULL;
tb = insert(text_words, tb);
or maybe:
Table tb = init_table();
tb = insert(text_words, tb);
but you need a seriously upgraded version of init_table(), such as:
Table init_table(void)
{
Table root = malloc(sizeof(*head));
root->head = NULL;
return root;
}
Your code in insert() needs to ensure that it does not dereference a null pointer (instead of an indeterminate pointer).
Table insert(Key_Type key, Table root)
{
tree_ptr t = (tree_ptr)malloc(sizeof(*t)); // Fixed size
t->element = key;
t->left = t->right = NULL;
if (root == NULL)
{
root = init_table();
root->head = t;
}
else
{
…
}
return root;
}
Given the Key_Type is a char * in disguise, you may need to review how you save the keys in the tree structure; you may need to use strdup() to copy the data. It is impossible to say for sure without seeing how you are managing the strings that you pass to the insert() function. It could be OK to just save the pointer if the calling code ensures that a new pointer is passed each time. OTOH, if the same pointer is passed each time, you definitely need to copy the data, and using strdup() is a sensible way of doing that. Note that strdup() is standard on POSIX; it is not part of standard C.
Here's one major problem:
tree_ptr t = (tree_ptr) malloc(sizeof(tree_ptr));
should be:
tree_ptr t = (tree_ptr) malloc(sizeof(struct node));
Your code doesn't actually do any binary search. Indeed, it just infinitely recurses creating new nodes. Try something more like this:
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct Node
{
char *element;
struct Node *left;
struct Node *right;
} Node;
typedef struct
{
Node *root;
size_t size;
} Tree;
void Tree_init(Tree *t);
Node *Tree_insert(Tree *t, const char *key);
void Tree_insert_r(Node *subtree, Node *n, size_t size);
void Tree_pre_order_r(Node *subtree);
void Tree_init(Tree *t)
{
t->root = NULL;
t->size = 0;
}
Node *Tree_insert(Tree *t, const char *key)
{
Node *ret = (Node*) malloc(sizeof(Node));
if (ret)
{
ret->left = ret->right = NULL;
if ((ret->element = strdup(key))) /* make a copy of key */
{
if (NULL != t->root)
Tree_insert_r(t->root, ret, t->size);
else
t->root = ret;
++t->size;
}
else
{
free(ret);
ret = NULL;
}
}
return ret;
}
void Tree_insert_r(Node *subtree, Node *n, size_t size)
{
int cmp = strcmp(n->element, subtree->element);
if (cmp < 0 || (cmp == 0 && size % 2 == 0))
{
if (NULL != subtree->left)
subtree = subtree->left;
else
{
subtree->left = n;
return;
}
}
else
{
if (NULL != subtree->right)
subtree = subtree->right;
else
{
subtree->right = n;
return;
}
}
Tree_insert_r(subtree, n, size);
}
void Tree_pre_order_r(Node *subtree)
{
if (NULL == subtree)
return;
fprintf(stdout, "'%s'\n", subtree->element);
Tree_pre_order_r(subtree->left);
Tree_pre_order_r(subtree->right);
}
int main()
{
Tree t;
Tree_init(&t);
Tree_insert(&t, "Hello");
Tree_insert(&t, "World!");
Tree_insert(&t, "etc.");
Tree_pre_order(t.root);
return 0;
}

pointers and values

I have written the following code, and it prints the root value correctly, but not the ret value. Here a memory address is potentially printed (1707388). I believe that ret could now be modified and the result would be seen in main. Any help is appreciated.
#include <stdlib.h>
struct node{
int value;
int order;
struct node *left;
struct node *right;
};
typedef struct node node_t;
node_t array[10];
void createTree(node_t *p, int order){
p->value = rand()%10;
p->order = order;
printf("%i", p->value);
printf(" ");
printf("%i\n", p->order);
if (!order){
p->left = NULL;
p->right = NULL;
return;
}
order--;
createTree(&p->left, order);
createTree(&p->right, order);
}
void traverse(node_t *current, node_t *ret, int size){
printf("%i\n", current->value);
if (current->value > size){
ret = current;
traverse(&current->left, &ret, size);
traverse(&current->right, &ret, size);
}
return;
}
int main(void){
node_t *root = &array[0];
node_t *ret;
srand(time(NULL));
createTree(root, 4);
int i = 3;
printf("%s", "root-value: ");
printf("%i\n", root->value);
traverse(root, ret, i);
printf("%s", "root-value: ");
printf("%i\n", root->value);
printf("%i\n", ret->value);
return 1;
}
This:
void createTree(node_t *p, int order)
Should be
void createTree(node_t **p, int order)
Otherwise you are modifying a local node_t pointer, instead of the one outside the function. Your tree isn't being built properly either.
You are passing ret by value to
void traverse(node_t *current, node_t *ret, int size){
When the function changes ret, the changes do not propagate back to the caller.
This means that ret in main() remains uninitialized, and the behaviour of your code is undefined.
To fix this, make traverse either return ret, or take it as node_t**.
There are few issues with the code.
First, you don't correctly allocate the memory for nodes. In your code, you are passing wrong pointer type, futhermore, pointer to uninitialized area.
Here, how it can be used differently:
node_t *createTree(int order)
{
node_t *result = malloc(sizeof(*result));
result->value = rand() % 10;
result->order = order;
if (order)
{
result->left = createTree(order - 1);
result->right = createTree(order - 1);
}
else
{
result->left = result->right = 0;
}
return result;
}
Then, your traverse function need some block to restrict agains failed search:
node_t *traverse(node_t *current, int size)
{
node_t *ret = NULL;
if (current->value > size)
{
// assuming current node fit - stops the search
ret = current;
}
if (!ret && current->left)
{
// try left node
ret = traverse(current->left, size);
}
if (!ret && current->right)
{
// try right node
ret = traverse(current->right, size);
}
return ret;
}
In case you need (usually you do), here is a destroyTree:
void destroyTree(node_t *node)
{
if (!node) return; // we treat NULL as a valid pointer for simplicity
destroyTree(node->left);
destroyTree(node->right);
free(node);
}
And here is a usage example:
node_t *root, *found;
root = createTree(4);
found = traverse(root, 3);
if (found)
{
printf("Found!");
}
destroyTree(root);
In traverse(node_t *current, node_t *ret, int size), ret is a stack variable. In other words, you are passing the pointer by value, instead of passing it by reference.
What have you done at the moment is essentially the same as:
int f(int i) {
...
i = <any value>;
...
}
In this case you are modifying only a copy of the value.
In your program, you are also modifying a copy of the pointer. Outside of the function the pointer stays not modified.
If you want to modify it, you need to pass a pointer to it:
void traverse(node_t *current, node_t **ret, int size){
...
*ret = current;
...
return;
}
The same for createTree().

Resources