Destroying a double threaded binary tree - c

So we have been asked to implement double threaded binary tree. They give us the function declarations and structures involved and we're supposed to give the function definitions.
The structure of a node of binary tree:
typedef struct node
{
int data;
struct node *left;
struct node *right;
int rightThread;
int leftThread;
} Node;
The tree structure:
typedef struct tree
{
Node *root;
} Tree;
Now i don't know why they ask us to implement this using two structures (one for tree and one for node) but we cannot change these.
I have so far managed to insert nodes into the threaded tree, etc, etc but am having trouble with destroying the tree
We have been asked to implement it in the following way:
void tree_destroy(Tree *tree);
{
//TODO
}
void destroy(Node *r)
{
//TODO
}
I have implemented it as follows:
void destroy(Node *r)
{
if(r==NULL)
return;
{
destroy(r->left);
destroy(r->right);
}
free(r);
}
void tree_destroy(Tree *t)
{
if(t->root==NULL) return;
destroy(t->root);
free(t);
}
But there seems to be some problem with my code because there is a segmentation fault. Can someone please help me spot it OR have another way to implement the given functions?
EDIT:
The main function call:
Tree my_tree;
tree_initialize(&my_tree);
.
.
.
tree_destroy(&my_tree);
The function tree_initialize:
void tree_initialize(Tree *tree)
{
tree->root=NULL;
}
When i have to add a new node to the tree, i initialize it in the following way:
Node* newnode=(Node*)malloc(sizeof(Node));
newnode->data=data;
newnode->left=newnode->right=NULL;
newnode->rightThread=newnode->leftThread=1;

The free(t); in tree_destroy is the problem: tree_initialize doesn't allocates struct tree, so tree_destroy should not free it.
Prototypes of the function tree_initialize assumes and the code
Tree my_tree;
tree_initialize(&my_tree);
.
.
.
tree_destroy(&my_tree);
makes my_tree to be stack, not heap variable and it could not and should not be free'd.
However, there is an approach to make Tree structure to be heap variable. In this case tree_initialize should looks like
Tree *tree_initialize()
{
Tree tree = malloc (sizeof(tree));
if (!tree) return NULL;
tree->root=NULL;
return tree;
}
and your initial tree_destroy containing free for Tree would be proper solution, but main should calls them like this:
Tree *my_tree = tree_initialize();
if (!my_tree) /* ERROR */
.
.
.
tree_destroy(my_tree);
Please note the extra checks for malloc fails in Tree allocation in tree_initialize and main and absence of & in tree_destroy call as well as in other functions like tree_insert and tree_delete using Tree * as an argument..

Related

Segmentation fault- queue won't initialize

The above code throws a segmentation fault and I am racking my brain to see where it is. The queue doesn't get initialized. I have been looking at the code for the longest time and i cannot identify what is going wrong.
typedef struct node node;
struct node
{
int data;
node *link;
};
typedef struct list
{
node *head;
node *tail;
int number_of_nodes;
}s_list;
typedef struct queue
{
s_list *ptr_list;
}queue;
void list_initialize(s_list* ptr_list) //debugger says this line is a problem? But seems fine to me?
{
ptr_list->head=NULL;
ptr_list->tail=NULL;
ptr_list->number_of_nodes=0;
}
void queue_initialize(queue* queue_list)
{
list_initialize(queue_list->ptr_list);
}
int main()
{
queue queue;
queue_initialize(&queue); //Have used a debugger and this isn't succesfull.
}
I cannot change the variable names or structures because this is part of an assignment i am supposed to fill.
I have tried changing the queue_initialization function to:
void queue_initialize(queue* queue_list)
{
queue_list=malloc(sizeof(queue));
list_initialize(queue_list->ptr_list);
}
There is still a segmentation fault
ptr_list is never initialized so in list_initialize() you are writing to random memory. In queue_initialize() you need something like this:
void queue_initialize(queue* queue_list)
{
queue_list->ptr_list = malloc(sizeof(s_list));
list_initialize(queue_list->ptr_list);
}

How can I save changes on a dynamic tree on c?

I'm building a database for a project, every entry has an RB-Tree that contains its attributes, but with the function that I made I cannot save the changes of the trees. I create and link the new nodes but when I return the new nodes are lost
x is the attribute (relation) identifier, used to look inside the tree and see if the relation already exists or not. id_orig is the entry of the database which I have to ad the relation to. tree * radice is the root of the tree and tree * nil is the nil pointer (substitute to NULL).
Add_rel_list is the function used to add a new relation after adding it on a new tree node if there isn't one.
insert fixup is used to check that the RB-Tree is balanced and respects it's definition
this is the add attribute function
struct tree *insert(unsigned long int x, char id_orig[50], char nome_relazione[50], struct tree *radice, struct tree * nil){ /*devo creare un nuovo nodo dell'albero */
if(radice==nil){
//this part is used to create a new root of the tree
}
else{
struct tree *newleaf=malloc(sizeof(struct tree)); /*creating a new node*/
//struct rel_list *lista=malloc(sizeof(struct rel_list));
newleaf->codice_rel=x; /*assign the node number*/
//newleaf->rel=lista; //link the list
newleaf->nome_rel=(char*)malloc(strlen(nome_relazione)+1);
strcpy(newleaf->nome_rel, nome_relazione);
newleaf->rel=add_rel_list(newleaf->rel, id_orig); /*helper function to add the list names*/
newleaf->num_rel=1; /*metto a 1 la quantit‡ del tipo di relazioni esistenti*/
struct tree *y= nil;
struct tree *w= radice;
while(w!=nil){
y=w;
if(newleaf->codice_rel<w->codice_rel){
w=w->left;
}
else{
w=w->right;
}
newleaf->prev=y;
if (y==nil){
radice=newleaf; //l'albero Ă‹ vuoto
}
else if(newleaf->codice_rel<y->codice_rel){
if(newleaf->codice_rel<y->left->codice_rel){
newleaf->right=y->left;
}
else{
newleaf->left=y->left;
}
y->left=newleaf;
}
else{
if(newleaf->codice_rel<y->right->codice_rel){
newleaf->right=y->right;
}
else{
newleaf->left=y->right;
}
y->right=newleaf;
}
newleaf->black=0;
insert_fixup(radice, newleaf, nil);
return radice;
}
}
}
struct tree *insert_rel(unsigned long int x, char *id_orig, struct tree *radice, struct tree *nil, char *id_dest, char *nomerel, controllo * controllore){
//non relevant to the problem
return radice;
}
void insert_fixup(struct tree *radice, struct tree* nuovo, struct tree *nil){
//this function is used to balance the tree
}
the function should create a new node and link it inside the tree. the calls that are in the function and that I did not post are irrelevant to the problem, leftrotate and rightrotate are for the manipulation of the RB-Tree. when, later on, I look inside the tree for the attributes (relations) the only one saved is the first one, the root of the tree. using gdb the linking is correct but when I return to the main part of the code I lose all the new nodes of the tree

Binary Tree of Strings returning wrong order

I am fairly new to C and have been learning from K&R's book The C Programming Language.
After doing the exercises on Binary trees I wanted to make a header for binary trees for
char*, long and double.
There is a function in the following code that has been giving me grief - it should fill an array of character pointers with the values stored in the tree in lexicographical order however it has a bug somewhere. Here's the code for the String Tree Header btree.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/************** TYPES **************/
typedef struct ctree
{
char *name;
ctree *left;
ctree *right;
};
/************** Globals **************/
static int c_inc = 0;
/************** Function Prototypes **************/
ctree *add_to_c_tree (ctree *cnode, char *name);
void print_c_tree (ctree *cnode);
ctree *c_tree_alloc (void);
void c_tree_free (ctree *cnode);
void return_c_tree (ctree *cnode, char **array);
/************** Function Definitions **************/
/* add_to_c_tree() : Adds a new node to a *character binary tree */
ctree *add_to_c_tree (ctree *cnode, char *name){
/* If the node is null, allocate memory for it,
* copy the name and set the internal nodes to null*/
if(cnode == NULL){
cnode = c_tree_alloc();
cnode->name = strdup(name);
cnode->left = cnode->right = NULL;
}
/* If initialised then add to the left node if it is lexographically
* less that the node above it else add it to the right node */
else{
if(strcmp(name, cnode->name) < 0)
cnode->left = add_to_c_tree(cnode->left,name);
else if(strcmp(name, cnode->name) > 0)
cnode->right = add_to_c_tree(cnode->right,name);
}
return cnode;
}
/* print_c_tree() : Print out binary tree */
void print_c_tree(ctree *cnode){
if (cnode != NULL) {
print_c_tree(cnode->left);
printf("%s\n",cnode->name);
print_c_tree(cnode->right);
}
}
/* return_c_tree() : return array of strings containing all values in binary tree */
void return_c_tree (ctree *cnode, char **array){
if (cnode != NULL) {
return_c_tree (cnode->left,array+c_inc);
c_tree_free(cnode->left);
*(array+c_inc++) = strdup(cnode->name);
// printf("arr+%d:%s\n", c_inc-1,*(array+(c_inc-1)));
return_c_tree (cnode->right,array+c_inc);
c_tree_free(cnode->right);
}
}
/* c_tree_alloc() : Allocates space for a tree node */
ctree *c_tree_alloc(void){
return (ctree *) malloc(sizeof(ctree));
}
/* c_tree_free() : Free's Memory */
void c_tree_free (ctree *cnode){
free(cnode);
}
Which I have been testing with bt.c:
#include "btree.h"
int main(void){
ctree *node = NULL; char *arr[100];
node = add_to_c_tree(node, "foo");
node = add_to_c_tree(node, "yoo");
node = add_to_c_tree(node, "doo");
node = add_to_c_tree(node, "woo");
node = add_to_c_tree(node, "aoo");
node = add_to_c_tree(node, "boo");
node = add_to_c_tree(node, "coo");
print_c_tree(node);
return_c_tree(node,arr);
for (int i = 0; i < 7; ++i)
{
printf("%d:%s ..\n",i, arr[i]);
}
return 0;
}
The reason for this question is that I have been having issues with the return_c_tree() function, which is meant to mimic the behaviour of K&R's print_c_tree() function except instead of recursively calling itself until a NULL ptr and printing out the name of the nodes in lexicographical order it is meant to add their names to an array of character ptrs and free the nodes memory.
However the output I get when run as above is:
aoo
boo
coo
doo
foo
woo
yoo
0:aoo ..
1:(null) ..
2:boo ..
3:doo ..
4:foo ..
5:coo ..
6:(null) ..
Which shows that the print function works fine but the return function obviously isn't.
The confusing thing is that if the call to printf() in return_c_tree() is uncommented this is the result:
aoo
boo
coo
doo
foo
woo
yoo
arr+0:aoo
arr+1:boo
arr+2:coo
arr+3:doo
arr+4:foo
arr+5:woo
arr+6:yoo
0:aoo ..
1:(null) ..
2:boo ..
3:doo ..
4:foo ..
5:coo ..
6:(null) ..
Which implies that it actually does add the strings in the right order.
Also I have tried it without the c_inc variable -> ie just incrementing array
before passing it to the right node which the produces the same results from the printf
in return_c_tree() but different from main:
arr+-1:aoo
arr+-1:boo
arr+-1:coo
arr+-1:doo
arr+-1:foo
arr+-1:woo
arr+-1:yoo
0:foo ..
1:yoo ..
2:coo ..
3:(null) ..
4:(null) ..
5:(null) ..
6:(null) ..
I'm rather confused, so If anyone can help I would appreciate it greatly. I'm sure I'm just incrementing it in the wrong place but I can't work out where.
I thought I had finally understood pointers but apparently not.
Best
P
Your problem is how you handle your pointer to array when you recursively call. This will fix your return_c_tree function:
void return_c_tree (ctree *cnode, char **array)
{
if (cnode != NULL) {
return_c_tree (cnode->left,array); // <--- CHANGED 2ND PARAM
c_tree_free(cnode->left);
*(array+c_inc++) = strdup(cnode->name);
return_c_tree (cnode->right,array); // <--- AGAIN, CHANGED 2ND PARAM
c_tree_free(cnode->right);
}
}
You're using a global variable c_inc to keep track of the current index into the array. However, when you recursively called return_c_tree, you passed in array+c_inc, but you did not offset c_inc to account for this. Basically, you double-counted c_inc each time.
While this solves your particular problem, there are some other problems with your code.
In general, using global variables is asking for trouble. There's no need to do it here. Pass c_inc as a parameter to return_c_tree.
Also, mixing global variables with recursion is especially prone to problems. You really want recursive routines to keep their state on the stack.
As a commenter pointed out, all of your code in btree.h should really be in btree.c. The point of header files is to define an interface, not for code.
(This is more stylistic) Your return_c_tree function is really two distinct functions: copy the elements of the tree (in order) into the array, and free the memory used by the tree. These two operations are conceptually distinct: there are times that you'll want to do one and not both. There can be compelling performance (or other) reasons to mix the two, but wait until you have some hard evidence.

How to delete subtree in BST C language?

I wanna make pop function to delete the node and subtree of the node. Here is my code
void pop(struct data *node,int num)
{
if(node)
{
if(node->num==num)
{
pop(node->left,num);
pop(node->right,num);
free(node);
node=NULL;
}
else
{
if(num> node->num)
pop(node->right,num);
else if (num< node->num)
pop(node->left,num);
}
}
}
void pre(struct data *node)
{
if(node)
{
printf("%d ",node->num);
pre(node->left);
pre(node->right);
}
}
void main()
{
push(&root,37);
push(&root,20);
push(&root,45);
push(&root,5);
push(&root,15);
push(&root,40);
push(&root,50);
pre(root);
pop(root,5);
pre(root);
getchar();
}
Pre function works well before I use pop. But after I used the pop function, it's break. Could anyone knows where's the mistake?
In pop, you're doing: node=NULL; -- but this only affects the copy of the pointer that was passed to the function, not the pointer in the original tree. Your tree retains the pointer to the data you've now freed. The next time you do much with the tree, you try to dereference that pointer, and things fall down and go boom (at least you hope they do -- even worse, sometimes they might seem to work).
One way to fix this is to pass a double pointer to pop:
void pop(struct data **node, int num) {
if ((*node)->num == num)
// ...
free(*node);
*node = NULL;
}
}
Now you're changing the pointer in the tree instead of changing the copy of it your function received.
This still won't work quite right though -- you're depending on pop(child, num); to destroy the sub-trees of the current node, but unless their num is set to the same value, they won't delete anything, just travel down the tree looking for a node with a matching num.
You probably want one function to walk the tree finding the node you care about, then a second one that walks the tree starting from a designated node, and (unconditionally) destroys that node and its sub-trees.
Well your pop function should be like this:
struct data* pop(struct data *node,int num)
{
struct data* temp=null;
if(node)
{
if(node->num==num)
{
if(node->left)
pop(node->left,node->left->num);
if(node->right)
pop(node->right,node->right->num);
free(node);
}
else
{
if(num> node->num)
temp=pop(node->right,num);
else if (num< node->num)
temp=pop(node->left,num);
if(node->right==temp)
node->right=null;
else if(node->left==temp)
node->left=null;
return temp;
}
}
return node;
}
This will work as far as you have the logic to nullify the root of the tree from where it is being called, if the desired node tuned out to be root of the tree.

Traverse tree without recursion and stack in C

How to traverse each node of a tree efficiently without recursion in C (no C++)?
Suppose I have the following node structure of that tree:
struct Node
{
struct Node* next; /* sibling node linked list */
struct Node* parent; /* parent of current node */
struct Node* child; /* first child node */
}
It's not homework.
I prefer depth first.
I prefer no additional data struct needed (such as stack).
I prefer the most efficient way in term of speed (not space).
You can change or add the member of Node struct to store additional information.
If you don't want to have to store anything, and are OK with a depth-first search:
process = TRUE;
while(pNode != null) {
if(process) {
//stuff
}
if(pNode->child != null && process) {
pNode = pNode->child;
process = true;
} else if(pNode->next != null) {
pNode = pNode->next;
process = true;
} else {
pNode = pNode->parent;
process = false;
}
}
Will traverse the tree; process is to keep it from re-hitting parent nodes when it travels back up.
Generally you'll make use of a your own stack data structure which stores a list of nodes (or queue if you want a level order traversal).
You start by pushing any given starting node onto the stack. Then you enter your main loop which continues until the stack is empty. After you pop each node from the stack you push on its next and child nodes if not empty.
This looks like an exercise I did in Engineering school 25 years ago.
I think this is called the tree-envelope algorithm, since it plots the envelope of the tree.
I can't believe it is that simple. I must have made an oblivious mistake somewhere.
Any mistake regardless, I believe the enveloping strategy is correct.
If code is erroneous, just treat it as pseudo-code.
while current node exists{
go down all the way until a leaf is reached;
set current node = leaf node;
visit the node (do whatever needs to be done with the node);
get the next sibling to the current node;
if no node next to the current{
ascend the parentage trail until a higher parent has a next sibling;
}
set current node = found sibling node;
}
The code:
void traverse(Node* node){
while(node!=null){
while (node->child!=null){
node = node->child;
}
visit(node);
node = getNextParent(Node* node);
}
}
/* ascend until reaches a non-null uncle or
* grand-uncle or ... grand-grand...uncle
*/
Node* getNextParent(Node* node){
/* See if a next node exists
* Otherwise, find a parentage node
* that has a next node
*/
while(node->next==null){
node = node->parent;
/* parent node is null means
* tree traversal is completed
*/
if (node==null)
break;
}
node = node->next;
return node;
}
You can use the Pointer Reversal method. The downside is that you need to save some information inside the node, so it can't be used on a const data structure.
You'd have to store it in an iterable list. a basic list with indexes will work. Then you just go from 0 to end looking at the data.
If you want to avoid recursion you need to hold onto a reference of each object within the tree.

Resources