How can i delete multiple nodes of a BST in c? - c

i have to delete some nodes of this BST
struct node {
char *value;
struct node *p_left;
struct node *p_right;
int usable;
};
the nodes that i have to delete are the ones with usable set to 0.
my question is, is it possible to make a sweep of the tree and delete all the nodes with usable == 0? all the resources i found online are about deleting a node containing a certain key, i tried to apply those but they didn't work
--edit:
the remove node function that i implemented was fine:
struct node* deleteNode(struct node* root, char *key) {
if (root == NULL)
{
return root;}
int cmp_result = strcmp(key, root->value);
if (cmp_result < 0)
root->p_left= deleteNode(root->p_left, key);
else if (cmp_result>0)
root->p_right= deleteNode(root->p_right, key);
else{
if (root->p_left==NULL) {
struct node *temp = root->p_right;
free(root);
return temp;
} else if(root->p_right==NULL){
struct node *temp = root->p_left;
free(root);
return temp;
}
struct node* temp = minValueNode(root->p_right);
strcpy(root->value, temp->value);
root->p_right= deleteNode(root->p_right, temp->value);
}
return root;
}
the problems arose because i called this function while traversing the tree, changing the structure of the tree while i'm using it
void pos2(struct node *head, char exactchar, int n)
{
if( head != NULL ) {
pos2(head->p_left, exactchar, n);
if (head->value[n]!=exactchar){
head = deleteNode(head, head->value);}
pos2(head->p_right, exactchar, n);
}
}
like this function that deletes a node if it has a word without a determined char in a determined position in it

is it possible to make a sweep of the tree and delete all the nodes with usable == 0?
Of course.
all the resources i found online are about deleting a node containing a certain key, i tried to apply those but they didn't work
I have no idea what, specifically, you tried. However, algorithms aimed at deleting the node having a specific key clearly do not solve the problem you have posed. They will use the BST-ness of the tree to efficiently find the specific node to delete, if it is present, and delete just that node.
Since your flag does not have a functional relationship with the keys on which the BST is ordered, you need to traverse the whole tree and delete every node you find that satisfies your criterion for doing so. Operationally, I would probably structure that as a depth-first traversal with post-order deletions (that is, consider whether to delete a given node after processing both its subtrees).

Related

Insert a node in a binary tree - Convert iterative to recursive

Repeated Question:
Recently I'm reading Data Structure(Binary Search Trees), I understand recursion very well and can trace it as well.
I used an approach which always worked for me i.e write a program with a loop, then eliminate loop and write a recursive function, the base condition will be same as loop exit condition.
But when it comes to writing one without my loop method, am getting failed.
I wasn't able to write a recursive function to insert a node in Binary Search Tree.(Though I understood it properly by referring the solution).
Kindly guide me, How to improve it?
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *left;//To store the address of the left child
struct node *right;//To store the address of the Right child
};
struct node * root;
struct node *createnewnode(int x)
{
struct node *n=(struct node *)malloc(sizeof(struct node));
n->data=x;
n->left=NULL;
n->right=NULL;
return n;
}
void Insert(int x)
{
struct node *a,*b;
struct node *temp=root;
if(root==NULL)
root=createnewnode(x);
else
{
while(1)
{
if(x<=temp->data)
{
if(temp->left!=NULL)
temp=temp->left;
else
{
a=createnewnode(x);
temp->left=a;
break;
}
}
else
{
if(temp->right!=NULL)
temp=temp->right;
else
{
a=createnewnode(x);
temp->right=a;
break;
}
}
}
}
}
int main()
{
root==NULL;//Empty Tree
Insert(15);
Insert(10);
Insert(20);
Insert(25);
return 0;
}
Edit: Sorry for not posting the code previously.
This is the code I have written for inserting a node, now how do I convert this into a recursive method?
The recursive Insert always asks the following question: can I insert a node in the current root? If not because root is not null then I have to check whether I have to recurse on the left or right subtree and call Insert recursively.
Something like the following should be enough to give you an idea on how to do it
Node* Insert(Node* root, int x) {
if (root == NULL)
return createnewnode(x);
else
if (x <= root->data)
root->left=Insert(root->left);
else
root->right=Insert(root->right);
}

Delete node from a C binary tree without messing it up

I am a beginner working on a C binary tree library.I am wondering on how could I delete a node from a binary tree without messing up the entire thing.Here is how I create the tree:
the structure:
struct Node {
int value;
struct Node *left;
struct Node *right;
};
typedef struct Node TNode;
typedef struct Node *binary_tree;
Creation of the tree:
binary_tree NewBinaryTree(int value_root) {
binary_tree newRoot = malloc(sizeof(TNode));
if (newRoot) {
newRoot->value = value_root;
newRoot->left = NULL;
newRoot->right = NULL;
}
return newRoot;
}
Adding elements to it:
void Insert(binary_tree *tree, int val) {
if (*tree == NULL) {
*tree = (binary_tree)malloc(sizeof(TNode));
(*tree)->value = val;
(*tree)->left = NULL;
(*tree)->right = NULL;
} else {
if (val < (*tree)->value) {
Insert(&(*tree)->left, val);
} else {
Insert(&(*tree)->right, val);
}
}
}
my question is basically how I could for example delete a left node,and then "link" the other nodes(or leaves) that were linked to that left node so the tree doesnt have a NULL leaf? Ex: if leaf 4 had 2 children(left3 and right8),then delete leaf 4, it link children left3 and right8 to the upper node(above leaf4).Its hard to explain im trying to do my best.
thank you
The algorithm for deleting from a BST looks conceptually like this:
You search for the node using its key.
Once you have found the node you check if it has only one child.
if it does, you remove the node and put on its place the child you just found.
if it doesn't, you search for the node with the minimum value key in the right subtree. Once you find it, you replace the key of the node you want to delete with this minimum key and you delete the minimum node in the right subtree.
How this whole concept works and how should it look in C code you can read for example here. My suggestion would be to first see this diagram, which illustrates all the possible scenarios.
Good luck!

Unable to print elements in binary search tree

My code is not printing the elements of binary search tree:
//x is the element to be inserted
//structure of program
typedef struct BST
{
int info;
struct BST *left;
//pointer to left node
struct BST *right;
//pointer to right node
}
bst;
//global root variable
bst *root;
void insert(int x)
{
bst *ptr,*sptr=root;
ptr=(bst*)malloc(sizeof(bst));
ptr->info=x;
if(root==NULL)
{
ptr->left=ptr->right=NULL;
root=ptr;
}
while(sptr!=NULL)
{
if(x<sptr->info)
{
sptr=sptr->left;
}
else
sptr=sptr->right;
}
sptr=ptr;
}
edit:
//following is the show function
void show()
{
bst *ptr=root;
while(ptr!=NULL)
{
//it will print untill the ptr is null
printf("%d",ptr->info);
ptr=ptr->left;
ptr=ptr->right;
}
}
Where is the value of root coming from? You're not passing in the value anywhere? Also, it is tough to help when we don't know the design of type bst.
It appears that you have the right idea. Create a node, and give it some data. If the root is null, then the new value is the root of the BST. After that you go ahead and find the first null node either in the left or right subtree of the root using the standard BST behavior. Finally, when you reach the end you go ahead and insert the last node in the proper place.
void insert(int x)
{
bst *ptr, *sptr=root; //<-- the value right here?
ptr = malloc(sizeof(bst));
ptr->info = x;
if(root == NULL)
{
ptr->left=ptr->right=NULL;
root=ptr;
}
while(sptr!=NULL)
{
if(x<sptr->info)
{
sptr=sptr->left;
}
else
sptr=sptr->right;
}
sptr=ptr; // <-- What is this line trying to do?
}
However, where did your updated tree go?
Since in C everything is passed by value, you're running into the problem where you're not seeing your updated tree after you leave this function. You need to go ahead and change the function to return a bst* type, and also maintain the root node during the entire function. Now the first line of code (*sptr = root) makes more sense! Finally, you were not setting the left and right fields of ptr to NULL. This means you were jumping over your if statements.
bst* insert(int x, bst *root)
{
bst *ptr, *sptr=root;
ptr = malloc(sizeof(bst));
ptr->left = NULL;
ptr->right = NULL;
ptr->info = x;
if(root == NULL)
{
ptr->left=ptr->right=NULL;
root=ptr;
return root;
}
while(sptr!=NULL)
{
if(x<sptr->info)
{
sptr=sptr->left;
}
else
sptr=sptr->right;
}
sptr=ptr;
return root;
}
What about the next function?
I just started looking at this one too. I am not used to the global variables in c, so I will go ahead and make two modifications. Let's make this recursive, and pass in the value of the root rather than using the global.
void show(bst *root)
{
if(root == NULL){
return;
}
printf("%d",root->info);
show(root->left);
show(root->right);
}
This will take in some value, and solve the tree recursively, and print as it reaches each node. Thus, it will print the root node (if it exists), and then print the left entire left subtree before it prints the right subtree.
Finally, looking at your main
I added the local variable root and thus you will have to remove the global variable named root outside of your main function. I also set the value of it to null so your first insert will fire correctly.
int main()
{
int i,n,x;
bst *root = NULL; //<-- I added this line of code to remove the global
puts("Enter number of elements");
scanf("%d",&x);
for(i=0;i<x;i++)
{
puts("Enter elements");
scanf("%d",&n);
root = insert(n, root);
}
show(root);
return 0;
}
I hope this helps!

Linked List of BST in C: Breadth First Search

I am writing a program that is a linked list of binary search trees. We are supposed to search for a number in the trees and print the tree and line number found. Because of this, we are supposed to use a Breadth-First Search function. I am getting a segmentation fault in my dequeue function and I am unsure why.
These are my structures:
typedef struct BST {
int value;
int treeNum;
struct BST* left;
struct BST* right;
}BST;
typedef struct rootList{
struct BST* root;
struct rootList* next;
}rootList;
typedef struct bfsQ{
struct BST* treeNode;
struct bfsQ* next;
}bfsQ;
This is my BFS function:
void BFS(rootList* listHead, int searchValue)
{
if(listHead->root == NULL)
{
printf("%d/tNO/tN/A/tN/A\n", searchValue);
}
else
{
bfsQ* newQueue = NULL;
BST* temp = NULL;
newQueue = malloc(sizeof(bfsQ));
newQueue->next = NULL;
enqueue(&newQueue, listHead->root);
while(newQueue != NULL)
{
temp = dequeue(&newQueue);
printf("Did this work?");
if(temp->value == searchValue)
printf("HI I WAS FOUND");
else
{
if(temp->left != NULL)
enqueue(&newQueue, temp->left);
if(temp->right != NULL)
enqueue(&newQueue, temp->right);
}
}
BFS(listHead->next, searchValue);
}
}
This is my enqueue:
void enqueue(bfsQ** qHead, BST* new_tree_node)
{
bfsQ *temp = malloc(sizeof(bfsQ));
BST *node;
temp->treeNode = new_tree_node;
temp->next = *qHead;
*qHead = temp;
node = temp->treeNode;
printf("%d\n", node->value);
}
This is my dequeue:
BST* dequeue(bfsQ** qHead)
{
bfsQ *temp, *first;
BST *newBST;
temp = (*qHead);
while(temp->next != NULL)
{
printf("THIS IS NOT NULL YET\n");
temp = temp->next;
}
first = temp;
newBST = first->treeNode;
free(temp);
return first->treeNode;
}
What am I doing wrong? The enqueue is working correctly, however my dequeue is not storing correctly.
EDIT: Apparently I need to:
"This function implements a variant of a level by level search or formally
called as the BREADTH FIRST SEARCH.
-> This function searches for a given value in the binary trees and it does that
by searching for level 1 in each binary trees, then moving on to level 2 if
it fails to find it that value in level 1 and so on.
-> Basically, you have to search for a given value in all the binary trees, one
level at a time, in the linked list simultaneously."
So I'm not sure if I need to search the whole tree, then move on, or look at each tree, line by line.
From the superficial look I had into the code, it looks generally ok (though I would have implemented some parts differently), but the last lines in dequeue() are certainly wrong:
first = temp;
newBST = first->treeNode;
free(temp);
return first->treeNode;
Accessing first->treeNode in the last line is catastrophic: first holds an address that has already been freed (temp and first refer to the same memory location). I think you wanted to return newBST instead:
return newBST;
You might as well throw first away, as it seems useless, and turn that into:
newBST = temp->treeNode;
free(temp);
return newBST;

Problem with pointers in binary search tree deletion

I am trying to implement binary search tree operations and got stuck at deletion.
11
/ \
10 14
Using inorder traversal as representation of tree initially output is 10 11 14.
Deleting node 10, output expected is 11 14 but I am getting 0 11 14.
Deleting node 14, output expected is just 11 but I am getting 0 11 67837.
Please explain why I am getting wrong output. I am not looking for any code :).
typedef struct _node{
int data;
struct _node *left;
struct _node *right;
} Node;
Node* bstree_search(Node *root, int key)
{
if(root == NULL){
return root;
}
// Based on binary search relation, key can be found in either left,
// right, or root.
if(key > root->data)
return bstree_search(root->right, key);
else if(key < root->data)
return bstree_search(root->left, key);
else
return root;
}
void bstree_insert(Node **adroot, int value)
{
// since address of address(root is itself address) is passed we can change root.
if(*adroot == NULL){
*adroot = malloc(sizeof(**adroot));
(*adroot)->data = value;
(*adroot)->right = (*adroot)->left = NULL;
return;
}
if(value > (*adroot)->data)
bstree_insert(&(*adroot)->right, value);
else
bstree_insert(&(*adroot)->left, value);
}
void bstree_inorder_walk(Node *root)
{
if(root != NULL){
bstree_inorder_walk(root->left);
printf("%d ",root->data);
bstree_inorder_walk(root->right);
}
}
void bstree_delete(Node **adnode)
{
//Node with no children or only one child
Node *node, *temp;
node = temp = *adnode;
if((*adnode)->right == NULL || (*adnode)->left == NULL){
if((*adnode)->right == NULL){
*adnode = (*adnode)->left;
}else{
*adnode = (*adnode)->right;
}
}else{ // Node with two children
}
free(temp);
}
int main()
{
Node *root = NULL;
Node *needle = NULL;
int i,elems[] = {11,10,14};
for(i = 0; i < 3; ++i)
bstree_insert(&root,elems[i]);
bstree_inorder_walk(root);
printf("\n");
needle = bstree_search(root, 10);
bstree_delete(&needle);
bstree_inorder_walk(root);
printf("\n");
needle = bstree_search(root, 14);
bstree_delete(&needle);
bstree_inorder_walk(root);
printf("\n");
}
Please explain why I am getting wrong
output.
Your delete function must also change the parent of the deleted Node. For example, when you delete the node holding 10, you must set the root Node's left child to NULL. Since you don't do this, when you later traverse the tree, you print out data that has already been freed.
I did not look at any code other than delete, so I can't make any guarantees about it working once this change is made.
You're getting wrong output because your deletion code is buggy (okay, maybe that's stating the obvious).
To delete from a binary search tree, you first find the node to be deleted. If it's a leaf node, you set the pointer to it in its parent node to NULL, and free the node. If it's not a leaf node, you take one of two leaf nodes (either the left-most child in the right sub-tree, or the right-most child in the left sub-tree) and insert that in place of the node you need to delete, set the pointer to that node in its previous parent to NULL, and delete the node you've now "spliced out" of the tree.
A couple of things really quick,
first when you allocate the node, you really should be doing the malloc on the sizeof the type (ie Node).
Second, if you have 2 children it looks like you are not really deleting the node and rebuilding the search tree by promoting one of the children.
Other people have already got you other obvious errors.

Resources