How can I save changes on a dynamic tree on c? - 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

Related

Destroying a double threaded binary tree

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

how to convert a given level of a binary search tree into a linked chain?

I have to do a function where, given an int n and a binary search tree, i have to convert the level n of the bst int a linked list.
for example if given the numer 2 and this tree
2
/ \
5 3
i have to make a liked list with 5 - 3
I have problems getting to the level given, and then getting each node on that level, because if i do reach the level i don't know how to reach the next node. Meaning, i can only get to the level on only one branch, and i cant think of any way to do it recursively.
so this is the struct for the bst and the linked chain:
struct nodo {
info_t dato;
nodo *anterior;
nodo *siguiente;
};
struct rep_cadena {
nodo *inicio;
nodo *final;
};
struct rep_binario {
info_t dato;
rep_binario *izq;
rep_binario *der;
};
and this is the function i cant figure out:
cadena_t nivel_en_binario(nat l, binario_t b)
i have tried using another function i already made, that calculates the height of a tree, but i can't stop on the wanted level.
nat altura_binario(binario_t b) {
if (b==NULL) return 0;
else return maximo(altura_binario(b->izq), altura_binario(b->der))+ 1;
}
where maximo() returns the highest number between the two given numbers.
You can do this by implementing Breadth-first_search algorithm, and modifying a little bit. Instead of enqueuing just nodes, you can enqueue pairs of (node, level) (where node level = parent level + 1), and then when enqueuing you can check if you have reached the desired level, and just output it as the result instead of queuing it further.
Pseudocode sketch:
target_level = ...read from input...
let level_nodes = ...an empty list...
let queue = ...an empty queue...
queue.enqueue((root_node, 0))
while queue is not empty:
node, level = queue.dequeue()
if level == target_level:
level_nodes.append(node)
else:
if node has left child:
queue.enqueue((left_child_node, level + 1))
if node has right child:
queue.enqueue((right_child_node, level + 1))

How to insert nodes in tree in C from right to left?

Now, I understand that code below works only for root and its children, but I don't know how to expand it. Every node must have children before passing on "grandchildren". Thank you.
void insert_node(IndexTree **root, Node *node) {
IndexTree *temp = (IndexTree*)malloc(sizeof(IndexTree));
memcpy(&temp->value.cs, node, sizeof(Node));
temp->left = NULL;
temp->right = NULL;
temp->tip=1;
if ((*root) == NULL) {
*root = temp;
(*root)->left = NULL;
(*root)->right = NULL;
}
else {
while (1) {
if ((*root)->right == NULL) {
(*root)->right = temp;
break;
}
else if ((*root)->left == NULL) {
(*root)->left = temp;
break;
}
}
}
Use recursive functions.
Trees are recursive data types (https://en.wikipedia.org/wiki/Recursive_data_type). In them, every node is the root of its own tree. Trying to work with them using nested ifs and whiles is simply going to limit you on the depth of the tree.
Consider the following function: void print_tree(IndexTree* root).
An implementation that goes over all values of the trees does the following:
void print_tree(IndexTree* root)
{
if (root == NULL) return; // do NOT try to display a non-existent tree
print_tree(root->right);
printf("%d\n", root->tip);
print_tree(root->left);
}
The function calls itself, which is a perfectly legal move, in order to ensure that you can parse an (almost) arbitrarily deep tree. Beware, however, of infinite recursion! If your tree has cycles (and is therefore not a tree), or if you forget to include an exit condition, you will get an error called... a Stack Overflow! Your program will effectively try to add infinite function calls on the stack, which your OS will almost certainly dislike.
As for inserting, the solution itself is similar to that of printing the tree:
void insert_value(IndexTree* root, int v)
{
if (v > root->tip) {
if (root->right != NULL) {
insert_value(root->right, v);
} else {
// create node at root->right
}
} else {
// same as above except with root->left
}
}
It may be an interesting programming question to create a Complete Binary Tree using linked representation. Here Linked mean a non-array representation where left and right pointers(or references) are used to refer left and right children respectively. How to write an insert function that always adds a new node in the last level and at the leftmost available position?
To create a linked complete binary tree, we need to keep track of the nodes in a level order fashion such that the next node to be inserted lies in the leftmost position. A queue data structure can be used to keep track of the inserted nodes.
Following are steps to insert a new node in Complete Binary Tree. (Right sckewed)
1. If the tree is empty, initialize the root with new node.
2. Else, get the front node of the queue.
……. if the right child of this front node doesn’t exist, set the right child as the new node. //as per your case
…….else If the left child of this front node doesn’t exist, set the left child as the new node.
3. If the front node has both the left child and right child, Dequeue() it.
4. Enqueue() the new node.

Operation ignoring via pointers in AVL tree

I am building an AVL tree, using this structure:
typedef struct node* nodep;
typedef struct node {
int postal_number;
int h; /* height */
nodep left, right, parent;
} Node;
Everything is working great: rotating, searching and inserting. The problem is with deleting a node. It deletes most of the node, except for few leaves after deleting most of the tree. My delete code (the problematic part) is:
int delete_postal(nodep* t, int in_postal){
nodep to_delete;
nodep* the_parent;
to_delete = search_postal((*t), in_postal);
the_parent = &(to_delete->parent);
/** if the node we want to delete is a leave **/
if (to_delete->right == NULL && to_delete->left == NULL) {
if (to_delete == (*the_parent)->right){ /* the node we want to delete is right son */
(*the_parent)->right = to_delete->right;
else { /* the node we want to delete is left son */
(*the_parent)->left = to_delete->left;
}
I made it so (*the_parent) will be the node himself in the tree, and when debugging it stepping into the if, it acts as if it did the deletion (making the child of the node the child of the node's father - I'm not dealing with malloc right now), but it just does not do it. The father keeps on pointing to the node that I would like to delete and not to NULL.
All the rest of the first deletion (nodes and leaves) works fine with this syntax.
Does somebody know what I am missing?

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