i have implemented a tree in C:
struct node
{
char *key;
struct node *left, *right;
};
// A utility function to create a new BST node
struct node *newNode(char *item)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->key = item;
temp->left = temp->right = NULL;
return temp;
}
// A utility function to do inorder traversal of BST
void inorder(struct node *root)
{
if (root != NULL)
{
inorder(root->left);
printf("%s\n", root->key);
inorder(root->right);
}
}
/* A utility function to
insert a new node with given key in
* BST */
struct node *insert(struct node *node, char *key)
{
/* If the tree is empty, return a new node */
if (node == NULL)
return newNode(key);
/* Otherwise, recur down the tree */
if (strcmp(key, node->key) < 0)
node->left = insert(node->left, key);
else
node->right = insert(node->right, key);
/* return the (unchanged) node pointer */
return node;
}
/* Given a non-empty binary search
tree, return the node
with minimum key value found in
that tree. Note that the
entire tree does not need to be searched. */
struct node *minValueNode(struct node *node)
{
struct node *current = node;
/* loop down to find the leftmost leaf */
while (current && current->left != NULL)
current = current->left;
return current;
}
/* Given a binary search tree
and a key, this function
deletes the key and
returns the new root */
struct node *deleteNode(struct node *root, char *key)
{
// base case
if (root == NULL)
return root;
// If the key to be deleted
// is smaller than the root's
// key, then it lies in left subtree
if (strcmp(key, root->key) < 0)
root->left = deleteNode(root->left, key);
// If the key to be deleted
// is greater than the root's
// key, then it lies in right subtree
else if (strcmp(key, root->key) > 0)
root->right = deleteNode(root->right, key);
// if key is same as root's key,
// then This is the node
// to be deleted
else
{
// node with only one child or no child
if (root->left == NULL)
{
struct node *temp = root->right;
free(root);
return temp;
}
else if (root->right == NULL)
{
struct node *temp = root->left;
free(root);
return temp;
}
// node with two children:
// Get the inorder successor
// (smallest in the right subtree)
struct node *temp = minValueNode(root->right);
// Copy the inorder
// successor's content to this node
root->key = temp->key;
// Delete the inorder successor
root->right = deleteNode(root->right, temp->key);
}
return root;
}
I have defined a function that takes the Tree as input and deletes a node from it if a condition is met:
void applyFilter(struct node *Tree)
{
if (Tree != NULL)
{
applyFilter(Tree->left);
applyFilter(Tree->right);
for (short i = 0; i < MAX_CONSTRAINTS; i++)
{
if (strchr(Tree->key, constraints[i].letter) != NULL)
{
// delete the word from the tree
Tree = deleteNode(Tree, Tree->key);
break;
}
}
}
}
But i got segmentation fault.
The main goal is to make it work, with as little memory as possible (running).
I think I understand the problem, and it is caused by recursion, because if I delete a node it will give me an empty tree.
If you can give me an example, even a different one i will be really gratefull, because i worked on it a lot, but i am totally stucked.
Thank you!
It happens in minValueNode() after the call of the deleteNode(), because result that the Tree is empty
It happens in minValueNode() after the call of the deleteNode(), because result that the Tree is empty
Basically you already understand what the problem is. You will need to check whether the tree is empty and default the value to something inside minValueNode before you start looping. Because the loop assumes that you have something and if you happen to have nothing, then it's a faulty assumption and causes segfault.
I am a rookie programmer and I have a project which implies using binary trees. All I have to do is to insert a node, delete a node and add two methods of tree traversal. The issue is I can't get my code to work. I decided to add few helper functions such as check_element and create_NewNode to help me out implement easier. I don't get an output on my console after running or it simply greets me with a runtime error. I have got a header file, IO.c file to store my functions and the main.c.to test header file Implemented functions.
Here is IO.c , used to store the functions.
#include <stdio.h>
#include <stdlib.h>
#include "Library.h"
struct node{
int data;
struct node *left;
struct node *right;
};
struct node *root;
/*-----------------------------------------------------------------------------------------*/
//function to determine if an element is already in the tree
void check_element( struct node *node, int value)
{
while( node != NULL ){
//checking if the value is here
if( value == node->data ){
printf("The element %d already exists in the tree!",value);
exit(0);
//if the value is smaller, go left
}else if( value < node->data ){
check_element( node->left, value );
//else go right
}else if( value > node->data ){
check_element( node->right, value );
//else the element was not found and we can add it to th tree
}else{
printf("Adding the element %d to the tree.",value);
exit(0);
}
}//end while
}//end check_element
/*-----------------------------------------------------------------------------------------*/
//helper function to crate a new node and set left and right pointers to NULL
struct node *create_NewNode( int value )
{
struct node *ptr;
struct node *temp = (struct node*)malloc(sizeof(struct node));
ptr = (struct node*)malloc(sizeof(struct node));
if( ptr == NULL){
printf("Memory allocation error!");
exit(-1);
}
//assigning the data to the newly created node
temp->data = value;
//setting left and right pointers to NULL
temp->left = NULL;
temp->right = NULL;
return temp;
}
/*-----------------------------------------------------------------------------------------*/
//function to add a new value to the tree;
struct node *insert_value( struct node *node, int new_value )
{
//checking if the element already exists to the tree
check_element( node, new_value );
//checking if the tree is empty
if( node == NULL ){
node = create_NewNode( new_value );
//if the value is smaller, we add it to the left
}else if( new_value < node->data ){
insert_value( node->left, new_value );
//else we add it to the right
}else{
insert_value( node->right, new_value );
}
return node;
}
/*-----------------------------------------------------------------------------------------*/
void printPostorder( struct node *node )
{
if (node == NULL){
printf("The tree is empty!");
exit(0);
}else{
//first go left
printPostorder( node->left );
//then go right
printPostorder( node->right );
//finally, print the node value
printf("%d", node->data);
}
}
/*-----------------------------------------------------------------------------------------*/
void inorder_traversal( struct node *node )
{
if( node == NULL) {
printf("The tree is empty!");
exit(0);
}else{
//first go left
inorder_traversal( node->left );
//print the node value
printf("%d ",node->data);
//then go right
inorder_traversal( node->right );
}
}
/*-----------------------------------------------------------------------------------------*/
This is the header file, called Library.h
//prototype for NewNode
struct node *create_NewNode( int value );
//prototype for insert_value
struct node *insert_value( struct node *node, int new_value );
//prototype for printPostordre
void printPostorder( struct node* node);
//prototype for printInorder
void inorder_traversal( struct node *node );
//prototype for check_element
void check_element( struct node *node, int value);
And, finally, the main.c: `enter code here:
#include <stdio.h>
#include <stdlib.h>
#include "Library.h"
int main()
{
// TEST CODE
struct node *root;
root = NULL;
insert_value(root, 1);
insert_value(root, 2);
insert_value(root, 3);
printPostorder( root );
inorder_traversal( root );
return 0;
}
PS: I did my best to write this code, but, as I said, I am a rookie and I'm pretty bad at coding.I'd also like to appologize for any grammar mistakes, i am not an englishman.
There may be more mistakes, but I read the create_node() and want to advice on it:
struct node *create_NewNode( int value )
{
struct node *ptr;
struct node *temp = malloc(sizeof(struct node));
ptr = malloc(sizeof(struct node));
if( ptr == NULL){
printf("Memory allocation error!");
exit(-1);
}
//assigning the data to the newly created node
temp->data = value;
//setting left and right pointers to NULL
temp->left = NULL;
temp->right = NULL;
return temp;
}
Here you are creating two nodes, while you intend to create only one. You treat temp as the new one, while you forget about ptr. You don't need to create another node!
What you need is the pointer of the tree, so that you add the newly constructed node at that tree (thus you could pass another parameter to that function, tree's pointer).
BTW, I removed the casts of malloc, as explained in Do I cast the result of malloc?
I suggest trying to fix your code after my advice. However, I will link you to treemanagement.c, which is c code for a tree, fully commented, and it's the way I learned about this data structure, it might can in handy in the future!
I forgot about this post. I have got it to work. This is what I used:
For the header file:
///\file Header.h
///\brief The header containing all the prototypes for our functions.
struct node *Create_node( int value );
void delete_value(struct node **root, int val_del) ;
void inorder_traversal( struct node *node );
void insert_value( struct node **head, int new_value );
void pre_order_traversal( struct node* node );
struct node* search_by_value(struct node* node, int value);
int random_value_generator(int domain);
For the implementation of the functions:
///\file Functions.c
///\brief C library implementation for BST.
#include <stdio.h>
#include <stdlib.h>
#include "Header.h"
//In this structure we'll be storing our BST.
struct node{
///\struct struct node
///\brief It represents our structure to store our BST.
int data;
struct node *left;
struct node *right;
};
/*-----------------------------------------------------------------------------------------------------*/
/*
Helper function which creates a new node, containing the desired value and setting left and right
pointers to NULL.
*/
struct node *Create_node( int value )
{
///\fn struct node *Create_node(int value)
///\brief Returns a new node, initialised with "value" and 2 NULL pointers, left and right.
///\param value The value which we want to initiliase the newly created node with.
//Creating the new Node and allocating memory to it.
struct node *new_node = (struct node*)malloc(sizeof(struct node));
//Assigning the desired value to the newly created node.
new_node->data = value;
//Setting left and right pointers to NULL;
new_node->left = NULL;
new_node->right = NULL;
return new_node;
};
/*-----------------------------------------------------------------------------------------------------*/
/*
The first traversal method.
*/
void pre_order_traversal( struct node* node )
{
///\fn pre_order_traversal(struct node* node)
///\brief A function used to 'traverse' the tree. It actually is a printing function.
///\param node It represents the starting point of printing.
//Checking if the tree is not empty.
if( node != NULL ) {
///It will print the root, then the left child, then the right child.
//Printing the node.
printf( "%d ",node->data );
//Printing the left child.
pre_order_traversal( node->left );
//Printing the right child.
pre_order_traversal( node->right );
}
}
/*-----------------------------------------------------------------------------------------------------*/
/*
A function which inserts a new node in the tree.
*/
void insert_value( struct node **head, int new_value )
{
///\fn insert_value(struct node **head, int new_value)
///\brief Inserts a new node into our BST.
///\param head This parameter is passed as a double pointer to avoid any conflicts with other fucntions.
/// and represents the starting point of insertion. The function will start searching for the appropriate
/// position to insert the value.
///\param new_value Is the new value which will be assigned to the new node;
//Initialising the pointer.
struct node *current = *head;
//Checking if the the current node is NULL, if it is, we create a new node.
if( current == NULL){
//If the root is NULL, then we create a new new node, containing the new value.
current = Create_node( new_value );
*head = current;
}else{
//Else, if the value is smaller, recur to the left.
if( new_value < current->data ){
insert_value( ¤t->left, new_value );
}else{
//Else recur to the right.
insert_value( ¤t->right, new_value );
}
}
}
/*-----------------------------------------------------------------------------------------------------*/
/*
The second traversal method.
*/
void inorder_traversal( struct node *node )
{
///\fn inorder_traversal(struct node* node)
///\brief A function used to 'traverse' the tree. It actually is the second printing function.
///\param node It represents the starting point of printing.
if( node != NULL ) {
///It will print the left child, then the root, then the right child.
//Printing the left child.
inorder_traversal( node->left );
//Printing the root.
printf( "%d ",node->data );
//Printing the right child.
inorder_traversal( node->right );
}
}
/*-----------------------------------------------------------------------------------------------------*/
/*
A function which deletes a node.
*/
void delete_value(struct node **root, int val_del)
{
///\fn void delete_value(struct node **root, int val_del)
///\brief It is the most complex function and it is used to delete a node.
/// There are multiple cases of deletion, such as: a leaf node (a node without any children),
/// a node with a child on the right, a node with a child on the left or a node with 2 children.
//We are starting from root, with two pointers: current and parent.
struct node *current = *root;
struct node *parent;
//We recur on the tree untill we find the node containing the value which we want to remove.
while (current->data != val_del) {
//Moving the parent to root. The root's parent is NULL. (root has no parent)
parent = current;
//If the value is greater the parent's value, recur right.
if (current->data > val_del) {
current = current->left;
}else{
//Else recur left.
current = current->right;
}
}
//Checking if the node is a leaf node. (no children on the left or right)
if ((current->left == NULL) && (current->right == NULL)) {
//Comparing the node's value with the value of its parent.
//If the value is smaller, we remove the left children.
if (current->data < parent->data) {
parent->left = NULL;
}else{
//Else we remove the right child.
parent->right = NULL;
}
free(current);
//Else, we check if it has a child on the left.
}else if (current->right == NULL) {
//Checking if our node is the root.
if(current == *root) {
//Using an aux to free the root, so the memory is not allocated to it anymore .
struct node *aux;
aux = (*root)->left;
free(*root);
(*root) = aux;
//If the node is not the root, we proceed.
}else{
//If the node's parent value is greater the the value of our node. If true, we replace
//the parent's left child with its left succesor and remove (free) the node.
if (current->data < parent->data) {
parent->left = current->left;
free(current);
}else{
//Else, we do the same thing, but for the parent's right child.
parent->right = current->left;
free(current);
}
}
//Else, we check if it has a child on the right.
}else if(current->left == NULL) {
//Checking if our node is the root.
if(current == *root) {
//Using an aux to free the root, so the memory is not allocated to it anymore.
struct node *aux;
aux = (*root)->right;
free(*root);
*root = aux;
//If the node is not the root, we proceed.
}else {
if (current->data < parent->data){
//If the node's parent value is smaller the the value of our node. If true, we replace
//the parent's left child with its right succesor and remove (free) the node.
//It is the mirrored code of the previous case.
parent->left = current->right;
free(current);
}else{
//Else, we do the same thing, but for the parent's right child.
parent->right = current->right;
free(current);
}
}
//Else, the node has 2 children. This is the last case.
}else if( (current->right != NULL) && (current->left != NULL)){
//In order to replace the root, we need to go one step to the right,
//and then all the way to the left, retrieve the smallest value,
//which will replace the root.
struct node *temp = current->right;
int aux;
while (temp->left != NULL) {
temp = temp->left;
}
//This si where we do the swap.
aux = temp->data;
current->data = aux;
temp = temp->right;
}
}
/*-----------------------------------------------------------------------------------------------------*/
/*
Helper function to determine if a value already exists in the tree.
*/
struct node* search_by_value(struct node* node, int value)
{
///\fn struct node* search_by_value(struct node* node, int value)
///\brief It is a function used to check if an element already exists in the tree.
/// If the fucntion returns NULL, it means that the element DOESN'T belong to the tree.
//Checking if the current node is empty or it has the value which we are looking for.
if (node == NULL || node->data == value){
return node;
free(node);
}
//If the value is greater, recur right.
if( value > node->data ){
return search_by_value(node->right, value);
}else{
//Else recur left.
return search_by_value(node->left, value);
}
//Returning NULL if the element wasn't found.
return NULL;
}
/*-----------------------------------------------------------------------------------------------------*/
/*
A simple function to generate random numbers,
between 0 and a domain.
*/
int random_value_generator(int domain)
{
///\fn int random_value_generator(int domain)
///\brief It generates random numbers between 0 and a set domain.
///\param domain It represents the dmain.(the upper boundry for our generation)
return rand()%domain;
}
And finally the the main file:
///\file main.c
///\brief The driver program for our BST library, containing a command line.
#include <stdio.h>
#include <stdlib.h>
#include "Header.h"
//Setting the root to NULL.(empty tree)
struct node *root=NULL;
int main()
{
//Preparing the command line. The choice is like a task selector.
int choice;
//Infinitely recuring until the user decides to exit or there is an error.
do{
//Printing the command line and acquiring the choice.
printf("\nWhat would you like to do ? Select:");
printf("\n1-Add value;\n2-Delete value;\n3-Print In-Order;\n4-Print Pre-Order;\n5-Random;\n6-Exit;");
printf("\n");
printf("\nYour choice:");
scanf("%d",&choice);
switch(choice){
//The first case is used for insertion of a new value.
case 1:{
//Initialising the local values.
int iterations=0,number=0,value=0,iterator=0;
//Setting up a pointer, for later use.
struct node *ptr;
//Acquiring the number of iterations.
printf("\nHow many values would you like to insert? Type a value:");
scanf("%d",&iterations);
//Inserting values as many times as we initiliased "iterations".
while( number < iterations ){
printf("\nValue[%d]=",iterator);
scanf("%d",&value);
//Using the pointer to check if the value already exists.
ptr = search_by_value( root, value );
if( ptr == NULL ){
//In case of ptr = NULL, we add it to the BST.
insert_value(&root,value);
value = 0;
}else{
//Else we ask for another value, without affectig the number of iterations.
printf("\nThe element %d already exists in the tree!",value);
//Resetting the pointer and the vaue to be reused.
value = 0;
ptr = NULL;
//A simple way to keep the loop consistent.
//If we want to insert 10 values and 1 would already exists,
//we would only have 9 values. This way, even if there a values
//already exists, we will still have to insert the appropriate
//nuber of values.
number--;
iterator--;
}
//Incrementing the iterators to prevent an ifinite loop.
number++;
iterator++;
}
//Reseting the iterator to be used later.
iterator=0;
break;
};//end case-1
//The second case is used for deletion.
case 2:{
//Initialising the value.
int d_value=0;
//Acquiering the value we want to delete.
printf("\nWhich value would you like to delete? \nType a value:");
scanf("%d",&d_value);
//Checking if the value exists in the tree.
struct node *ptr = search_by_value( root, d_value );
if( ptr != NULL ){
//If ptr != NULL, it means that the value exists in the tree
// and it can be deleted.
printf("\nDeleting %d !",d_value);
//Deleting the value.
delete_value(&root, d_value);
//Reseting the value for laer use
d_value = 0;
}else if( ptr == NULL ){
//Else the value does not belong to the tree, so it cannot be deleted.
printf("\nThe element %d doesn't belong to the tree!",d_value);
printf("\n");
//Resetting the pointer and the value for later use.
d_value = 0;
ptr = NULL;
}else{
//Else our tree is empty.
printf("\nEmpty Tree!");
}
break;
};//end case-2
//The third case is used for in-order traversal.
case 3:{
printf("\nIn-order traversal:");
inorder_traversal(root);
printf("\n");
break;
};//end case-3
//The fourth case is used for pre-order traversal.
case 4:{
printf("\nPre-order traversal:");
pre_order_traversal(root);
printf("\n");
break;
};//end case-4
//The fifth case is used for randomly inserting value into teh BST.
case 5:{
//Initialising the values.
int iterations=0,number=0,value=0,iterator=0,domain=0;
//Setting up a pointer for later use.
struct node *ptr;
//Acquiering the number of iterations.
printf("\nHow many values would you like to insert? Type a value:");
scanf("%d",&iterations);
//Acquiering the domain for the random generator.
printf("\nPlease type the domain for the randomly generated numbers.");
printf("\nPlease type a value:");
scanf("%d",&domain);
//Iterating until all the values have been successfully inserted.
while( number < iterations ){
//The new value to be inserted is generated using our fucntion.
value = random_value_generator(domain);
//Checking if the values already exists in the tree.
ptr = search_by_value( root, value );
if( ptr == NULL ){
printf("\nInserting %d!",value);
//If ptr = NULL, we can safely insert the value into our BST.
insert_value(&root,value);
//Resetting the value for later use.
value = 0;
}else{
//Else, we cannot insert the value, as it already exists.
printf("\nThe element %d already exists in the tree!",value);
//Resetting the pointer and the value.
value = 0;
ptr = NULL;
//Same trick to insert the exact number of values.
number--;
iterator--;
}
//Incrementing to prevent infinite looping.
number++;
iterator++;
}
//Resetting the iterator for later use.
iterator=0;
break;
};//end case-5
//The sixth case is used to exit the proram at will.
case 6:{
exit(0);
};//end case-6
//The default case occurs in case of error. (hope not)
default :{
printf("\nError!");
exit(-1);
};//end default
}//end switch
}while(1);//end while
return 0;
}
I used double pointers and that got rid of my problems. I hope this will help someone.
as a n exercise i am working on a binary search tree. I have managed to search through the binary tree, and add nodes, but now that i try to find a way to delete, i seem to be stuck at how to determine who is the parent of a node that is to be deleted.
So to start with i have this structure
struct BST_node {
struct double_linked_list *data;
struct BST_node *left;
struct BST_node *right;
};
and i have also a pointer for this structure that points to root..
struct BST_node *BST_email_root = 0;
I have this function to search for a Node
struct BST_node *BST_find_customer(struct BST_node *root, char *email) {
if (root==NULL)
return NULL;
if (strcmp(email,root->data->data->email)==0)
return root;
else
{
if (strcmp(email,root->data->data->email)==-1)
return BST_find_customer(root->left,email);
else
return BST_find_customer(root->right,email);
}
that i call inside other functions, by using
b = BST_find_customer(BST_email_root, email);
and i am trying to create the function to delete nodes..What i have to is this:
struct BST_node *BST_delete(struct BST_node *root, char *email)
{
struct BST_node *temp;
if (root==NULL)
return root;
else if(strcmp(root->data->data->email,email)>0)
root->left = BST_delete(root->left, email);
else if(strcmp(root->data->data->email,email)<0)
root->right = BST_delete(root->right, email);
else
{
if(root->left == NULL && root->right == NULL)
{
free(root);
root = NULL;
}
else if(root->right == NULL)
{
temp = root;
root = root->left;
free(temp);
}
else if(root->left == NULL)
{
temp = root;
root = root->right;
free(temp);
}
else
{
struct BST_node *maxNode = findMaxNode(root->left);//finding the maximum in LEFT sub-tree
root->data = maxNode->data; //Overwriting the root node with MAX-LEFT
root->left = BST_delete(root->left, maxNode->data);//deleted the MAX-LEFT node
}
return root;
}
}
by using this function also
struct BST_node *findMaxNode(struct BST_node *root)
{
if(root->right == NULL) return root;
findMaxNode(root->right);
}
However this doesnt work also and i get errors
Here is a solution, although it's not recursive .....
To delete a node N from a BST, you need to consider the 3 cases :
If N is a leaf, then no problem, just delete it
If N has only one son, just replace N by its son ; you'll need the pointer towards the father of N to do that
If N has two sons, then you can replace N by the leftest son of its right son, or by the rightest son of its left son to keep the order properties.
void *BST_delete(struct BST_node *root, char *email){
if (root==NULL)
return;
struct BST_node * father = NULL;
char which_son; //will help us in remembering if root is the right or left son of his father
while (strcmp(email,root->data->data->email)!=0){ //first, finding root and remembering who's root father
if(root==NULL) {
return ;
} else if (strcmp(email,root->data->data->email) < 0){
father = root;
root = root->left;
which_son = 'l';
} else {
father = root;
root = root->right;
which_son = 'r';
}
}
// now you have both the root node, and its father
if ( (root->right == NULL) && (root->left == NULL) ){ //case 1, if it's a leaf
free(root);
return;
} else if (root->left == NULL) { //case 2
if (which_son == 'l') {
father->left = root->right;
} else {
father->right = root->right;
}
} else { //case 3 : here i get the "rightest" son of root's left son
struct BSD_node * replacing_node = root->left;
while (replacing_node->right != NULL) {
replacing_node = replacing_node->right;
} //now replacing_node is a leaf, and can replace root
if (which_son == 'l') {
father->left = replacing_node;
replacing_node->left = root->left;
replacing_node->right = root->right;
} else {
father->right = replacing_node;
replacing_node->left = root->left;
replacing_node->right = root->right;
}
}
free (root);
}
I changed the return value of your function to void , since it might not need any return value.
It can be implemented in an easier way by simply replacing the 'data' field of one node by another, but i purposely implemented it in that fashion to emphasizes the fact that the node to delete is replaced by one of his descendants.
If it doesn't seem obvious to you that the node to suppress should be replaced by the rightiest (leftiest) son of its left (right) son, then check that these are the only 2 nodes which do not present the risk of breaking the order of your BSD.
Also, this function suffers a lot from being monolithic, it would enjoy being refactorised.
i was trying to understand this function founded online for deleting a node from a BST. There are some things i can't understand
This is the code :
struct Node* Delete(struct Node *root, int data) {
if (root == NULL) {
return NULL;
}
if (data > root->data) { // data is in the left sub tree.
root->left = Delete(root->left, data);
} else if (data > root->data) { // data is in the right sub tree.
root->right = Delete(root->right, data);
} else {
// case 1: no children
if (root->left == NULL && root->right == NULL) {
delete(root); // wipe out the memory, in C, use free function
root = NULL;
}
// case 2: one child (right)
else if (root->left == NULL) {
struct Node *temp = root; // save current node as a backup
root = root->right;
delete temp;
}
// case 3: one child (left)
else if (root->right == NULL) {
struct Node *temp = root; // save current node as a backup
root = root->left;
delete temp;
}
// case 4: two children
else {
struct Node *temp = FindMin(root->right); // find minimal value of right sub tree
root->data = temp->data; // duplicate the node
root->right = Delete(root->right, temp->data); // delete the duplicate node
}
}
return root; // parent node can update reference
}
Questions :
1) Why it is
if (data > root->data) { // data is in the left sub tree.
root->left = Delete(root->left, data);
shouldn't it be if(data < root->data) ? (same for the two lines of code right after)
2) the function return a pointer to node,does that mean that in the main function i have to do something like this?
int main(){
struct Node *tree=malloc(sizeof(Node));
...
struct Node *new_tree=malloc(sizeof(Node));
new_tree= Delete(tree,24);
So the function replace the old tree with a new tree without the node with the val 24?if i want the function to be of type void should i use double pointers?
For your first question you have right it should be: if(data < root->data).
For the second question not exactly. You obviously should define a pointer head which is the head of the tree and create an function which inserts data to bst, so this function does the malloc. All you nead in your main is the head pointer initialized to NULL in the beginning so it should look like:
int main(){
struct Node *tree=NULL;
int number=...;
...
input_to_bst(&tree,number);
...
new_tree= Delete(tree,24);
Also note that new tree doesn't need to have malloc since your function returns a pointer that already shows to a struct and what you do is that new_tree will also point this struct.
For your final question yes of course you could pass double pointer (in fact I followed this way in the definition of input_to_bst(&tree);).
An example of function input_to_bst definition could be:
void input_to_bst(treeptr* head,int number){
if((*head)==NULL){
(*head)=(treeptr)malloc(sizeof(struct tree));
(*head)->data=number;
(*head)->left=NULL;
(*head)->right=NULL;
}
else{
if(((*head)->data)>number) input_to_bst(&((*head)->left),number);
else (((*head)->data)<number) input_to_bst(&((*head)->right),number);
}
}
where we suppose that we have defined the structs:
struct tree{
int data;
struct tree* right;
struct tree* left;
};
typedef struct tree* treeptr;
I am trying to modify a BST to work with strings from the model in my book that works with integers. I am having a hard time with the modifying because of mallocing spacing for the string (i believe). I tested the code and it goes the proper direction when needed but fails when handling the strings. I have the all the functions working and testing but cant get delete running so if anyone could point me in the right direction I'd be grateful.
My struct treeNode is well a node for a tree.
typedef struct treeNode
{
char* data;
struct treeNode *left;
struct treeNode *right;
}treeNode;
And my delete function that takes in a node and string to be found
////////////////////////////////////////////////////////////////////////////
/////////////////////Delete function////////////////////////////////
/////////////////////////////////////////////////////////////////////
treeNode * Delete(treeNode *node, char *string)
{
//printf("broke before temp?"); //testing
treeNode *temp; //temporary node;
int compare; //do string cmp instead of int compare.
//printf("broke before compare");
//printf("broke after repair");
if(node==NULL) //if nothing in tree, can't delete (or aint here)
{
printf("Element Not Found");
}
else if(node != NULL){
compare = strcmp(string, node->data); //comparison variable to see if we traverse left or right
}
else if(compare > 0) //if we need to go right
{
//printf("going right");
node->right = Delete(node->right,string); //recursive with right subtree as root
}
else if(compare < 0) //if we need to go left
{
//printf("going left");
node->left = Delete(node->left,string); //recursive with left subtree as root
}
///////////////////////////////////////////////////
//////////IF we have found the element to delete///
//////////////////////////////////////////////////
else if(compare == 0)
{
//if the node has both a left and right subtree
if(node->right && node->left)
{
/* Here we will replace with minimum element in the right sub tree */
temp = FindMin(node->right); //sets temp node to smallest node
//printf("broke on find min");
free(node -> data); //free the data that is on the node being deleted
//printf("broke on free");
node->data = (char *)malloc(strlen(temp->data)+1); //allocates new memory for temp string
//printf("broke on malloc");
strcpy(node->data, temp->data); //copys temp string to the node
//printf("broke on strcpy");
node -> right = Delete(node->right,temp->data); //have to move down chain to replace
}
else //if it only have one child, find the child and replace
{
temp = node; //set node to temp for free
if(node->left == NULL) //if no left child set node to right
node = node->right;
else if(node->right == NULL) //if no right child set node to left
node = node->left;
printf("freeing %s",temp->data); //free string
free(temp->data); //free data
free(temp); //free node
}
}
return node;
}
Thank you again for your time and help.
EDIT: I have implemented this changes, and now it loops through without actually deleting a node. I think it is breaking when i set the node values where the case with no children is found.
EDIT2: This code works error was in different section of code! Thank you all for your help.
You are using strcmp(string, node->data); before you check if(node==NULL). In which case you get a segmentation fault.
Remove the first strcmp() which is still in there. Remove the brace { (and matching } ?) and the else just following the relocated strcmp().
if(node==NULL) {
printf("Element Not Found");
} else {
compare = strcmp(string, node->data);
if(compare > 0) {
...
}