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!
Related
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).
I am working on a C binary search tree library and I'm trying to write a function that will delete the left node of the tree subtree. Here's the struct of my tree:
struct Node {
int value;
struct Node *left;
struct Node *right;
};
typedef struct Node TNode;
typedef struct Node *binary_tree;
The tree is created like this:
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 element 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);
}
}
}
The delleftsubtreenode I did:
void delleftsubtree(binary_tree *tree){
if( (*tree)->value!=NULL )
{
free(&(*tree)->left);
delleftsubtree( &(*tree)->left);
}
else
{
printf("end");
}
}
This method compile,however when I try to call it the program just crash.I dont understand why or how else to do that function.
thank you!
As Olaf said in his comment, you have several problems; calling "free()" with a pointer then attempting to dereference it, and use of double indirection.
binary_tree* tree; /* why use a pointer to a pointer? */
Unless you intend to change the value of the pointer, this is extra work you don't want to be doing. All those "(*tree)->member" expressions are not needed if you follow the usual conventions, and I'm not convinced that you understand what "&(*tree)->left" is doing.
I'm not saying that you should never use a pointer to a pointer, I've done it myself, however you should only do it when there is a reason to be changing the value of the referenced pointer, or with a volatile pointer that might be changed by some external actor; this is unlikely and fairly rare outside of garbage collected and compacted pools (strings in some BASIC interpreters, for example) and the like.
Keep in mind that the "left" subtree of a node in the tree is a binary tree itself; it has both left and right nodes. You need to write a function that deletes a subtree at and below a given node. Once that's understood, removal of the left subtree below a node is as simple as:
void delSubtree(NodeT* subRoot)
{
if (subRoot != NULL)
{
delSubtree(subRoot->left);
delSubtree(subRoot->right);
free(subRoot);
}
}
void delLeftSubtree(NodeT* root)
{
if (root != NULL)
{
delSubtree(root->left);
root->left = NULL;
}
}
If this is homework, you should be solving these problems yourself, and I'm doing you no favors in giving you code samples. Understanding how to use pointers and linked data structures (lists, trees, and other graphs) is essential to becoming an accomplished C programmer.
Im working on a C library for binary tree, and Im wondering how I could save the value of the root of the tree to be able to display it later in a function.
My tree struct:
struct Node {
int value;
struct Node *left;
struct Node *right;
};
typedef struct Node TNode;
typedef struct Node *binary_tree;
The binary tree root is initialised with the 3 value like this:
caller:
tree = NewBinaryTree(3);
NewBinaryTree method:
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;
}
Basically I would like to be able to do a function that just display the value_root function even after adding elements to the binary tree and be able to still display the value_root value.This might be very basic but im learning C and im not sure.
thank you
In the caller: printf( "%d\n", tree->value )
– user3386109
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;
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.