How to delete subtree in BST C language? - c

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.

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

C recursively build tree using structure pointer

I'm now implementing Barnes-Hut Algorithms for simulating N-body problem. I only want to ask about the building-tree part.
There are two functions I made to build the tree for it.
I recursively build the tree, and print the data of each node while building and everything seems correct, but when the program is back to the main function only the root of the tree and the child of the root stores the value. Other nodes' values are not stored, which is weird since I printed them during the recursion and they should have been stored.
Here's some part of the code with modification, which I thought where the problem might be in:
#include<...>
typedef struct node{
int data;
struct node *child1,*child2;
}Node;
Node root; // a global variable
int main(){
.
set_root_and_build(); // is called not only once cuz it's actually in a loop
traverse(&root);
.
}
Here's the function set_root_and_build():
I've set the child pointers to NULL, but didn't show it at first.
void set_root_and_build(){
root.data = ...;
..// set child1 and child2 =NULL;
build(&root,...); // ... part are values of data for it's child
}
And build:
void build(Node *n,...){
Node *new1, *new2 ;
new1 = (Node*)malloc(sizeof(Node));
new2 = (Node*)malloc(sizeof(Node));
... // (set data of new1 and new2 **,also their children are set NULL**)
if(some condition holds for child1){ // else no link, so n->child1 should be NULL
build(new1,...);
n->child1 = new1;
//for debugging, print data of n->child1 & and->child2
}
if(some condition holds for child2){ // else no link, so n->child2 should be NULL
build(new2,...);
n->child1 = new2;
//for debugging, print data of n->child1 & and->child2
}
}
Nodes in the tree may have 1~2 children, not all have 2 children here.
The program prints out the correct data when it's in build() function recursion, but when it is back to main function and calls traverse(), it fails due to a segmentation fault.
I tried to print everything in traverse() and found that only the root, and root.child1, root.child2 stores the value just as what I've mentioned.
Since I have to called build() several times, and even in parallel, new1 and new2 can't be defined as global variables. (but I don't think they cause the problem here).
Does anyone know where it goes wrong?
The traverse part with debugging info:
void traverse(Node n){
...//print out data of n
if(n.child1!=NULL)
traverse(*(n.child1))
...//same for child2
}
You may not be properly setting the children of n when the condition does not hold. You might want this instead:
void set_root_and_build()
{
root.data = ...;
build(&root,...); // ... part are values of data for it's child
}
void build(Node *n,...)
{
n->child1 = n->child2 = NULL;
Node *new1, *new2;
new1 = (Node*) malloc(sizeof(Node));
new2 = (Node*) malloc(sizeof(Node));
// set data of new1 and new2 somehow (read from stdin?)
if (some condition holds for new1)
{
n->child1 = new1;
build(n->child1,...);
//for debugging, print data of n->child1
}
else
free(new1); // or whatever else you need to do to reclaim new1
if (some condition holds for new2)
{
n->child2 = new2;
build(n->child2,...);
//for debugging, print data of n->child2
}
else
free(new2); // or whatever else you need to do to reclaim new2
}
Of course, you should be checking the return values of malloc() and handling errors too.
Also, your traversal is a bit strange as it recurses by copy rather than reference. Do you have a good reason for doing that? If not, then maybe you want:
void traverse(Node *n)
{
...//print out data of n
if (n->child1 != NULL)
traverse(n->child1)
...//same for child2
}
The problem in your tree traversal is that you certainly process the tree until you find a node pointer which is NULL.
Unfortunately when you create the nodes, these are not initialized neither with malloc() nor with new (it would be initialized with calloc() but this practice in cpp code is as bad as malloc()). So your traversal continues to loop/recurse in the neverland of random pointers.
I propose you to take benefit of cpp and change slightly your structure to:
struct Node { // that's C++: no need for typedef
int data;
struct node *child1,*child2;
Node() : data(0), child1(nullptr), child2(nullptr) {} // Makes sure that every created are first initalized
};
And later get rid of your old mallocs. And structure the code to avoid unnecessary allocations:
if(some condition holds for child1){ // else no link, so n->child1 should be NULL
new1=new Node; // if you init it here, no need to free in an else !!
build(new1,...);
n->child1 = new1;
...
}
if (... child2) { ... }
Be aware however that poitners allocated with new should be released with delete and note with free().
Edit: There is a mismatch in your code snippet:
traverse(&root); // you send here a Node*
void traverse(Node n){ // but your function defines an argument by value !
...
}
Check that you didn't overllok some warnings from the compiler, and that you have no abusive cast in your code.

Deleting nodes in BST using free(N)

I'm coding a binary search tree and I'm having a little trouble finding a way to delete node effectively.
I have this code :
struct node* deleteNode(int i, struct node *N)
{
if (N==NULL)
{
return NULL;
}
else if (i<N->value)
{
N->size--;
N->lChild=deleteNode(i,N->lChild);
}
else if (i>N->value)
{
N->size--;
N->rChild=deleteNode(i,N->rChild);
}
else if (N->lChild==NULL)
{
return N->rChild;
}
else if (N->rChild==NULL)
{
return N->lChild;
}
else
{
N->size--;
N->value=findMin(N->rChild);
N->rChild=deleteNode(N->value,N->rChild);
}
return N;
}
And N is a node structure which have 5 fields : value, lChild, rChild, size, height.
In fact what I'm doing here is to make the tree not to point toward the node that I want to delete but when I'm trying to put something like :
else if (N->rChild==NULL)
{
free(N);
N=NULL;
return N->lChild;
}
Or every similar looking code, it doesn't work. Can someone point me in the right direction please?
Thank you.
First of all you're saying N=NULL and then calling N->lchild N is null and pointing to nothing so how do you expect to get the lchild value?
Since this is homework I won't give a direct answer but hints.
To delete the node, check if it has children, if it doesnt free it and remove references to it such as the parents child ptr.
If it has 1 child swap the ptr that points to the node you want to delete with the child and free the node. The same applies if you also have 2 children.

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