Given the below code what could I use to make a delete function? I have tried multiple things and I keep getting snagged on trying to get it to work. My main problem is trying to delete a node that has a left and right child. For a node that has no children I can just set its parent to point to null and free the node. For one child just set the parent to point to the child and free the node. How would I do it for a node with two children both conceptually and in my code?
#include<stdlib.h>
#include<stdio.h>
struct bin_tree {
int data;
struct bin_tree * right, * left;
} bin_tree;
typedef struct bin_tree node;
void help()//help
{
printf("Options:\n");
printf(" # -Put in any number to add it to the tree if not already there\n");
printf(" s # -Put in s and a number to search the tree for the number\n");
printf(" d # -Delete the number from the tree\n");
printf(" p -Put in p to print the tree\n");
printf(" ? -At any time you can press ? to display the help message\n");
printf(" Q -If you decide the leave the realm of the tree then you can press Q to quit this program\n");
}
int max(int a,int b)//max tree length
{
if(a>b)
return a;
else
return b;
}
int height(node* tree)//height
{
if(tree != NULL)
return(1 + max(height(tree->left),height(tree->right)));
else
return 0;
}
void insert(node ** tree, int val)//insert
{
node *temp = NULL;
if(!(*tree))
{
temp = (node *)malloc(sizeof(node));
temp->left = temp->right = NULL;
temp->data = val;
*tree = temp;
return;
}
if(val < (*tree)->data)
{
insert(&(*tree)->left, val);
}
else if(val > (*tree)->data)
{
insert(&(*tree)->right, val);
}
}
void print(node * tree)//print
{
if (tree)
{
print(tree->left);
printf("[%d] ",tree->data);
print(tree->right);
}
}
node* search(node ** tree, int val)
{//search
if(!(*tree))
{
return NULL;
}
if(val < (*tree)->data)
{
search(&((*tree)->left), val);
}
else if(val > (*tree)->data)
{
search(&((*tree)->right), val);
}
else if(val == (*tree)->data)
{
return *tree;
}
}
void main()
{
node *root;
node *tmp;
int no;
char ch, buff[500];
root = NULL;
printf("Options:\n");
printf(" # -Put in any intiger to add it to the tree if not already there\n");
printf(" s # -Put in s and a number to search the tree for the number\n");
printf(" d # -Delete the number from the tree\n");
printf(" p -Print the tree\n");
printf(" ? -At any time you can press ? to display the help message\n");
printf(" Q -If you decide the leave the realm of the tree then you can press Q to quit this program\n");
while(1){
printf(">");
fgets(buff,499,stdin); //grabs input from user
if(sscanf(buff,"%i",&no)==1){//decides if just a number
tmp = search(&root, no);//looks for number in the tree
if (tmp)
{
printf("Node already in tree!\n", tmp->data);
}
else
{
insert(&root, no);//if not in tree insert it
}
}
else if(sscanf(buff,"%c %i",&ch,&no)>=1)//checks if character
{
switch(ch)
{
case 's'://search for number
{
tmp = search(&root, no);
if (tmp)
{
printf("Node found=%d\n", tmp->data);
}
else
{
printf("Node not found in tree.\n");
}
break;
}
case 'd':
tmp = search(&root, no);
if (tmp)
{
//Call delete function
printf("Node %i deleted", no);
break;
}
else
{
printf("Node not found in tree.\n");
break;
}
case 'Q'://quit
exit(0);
case 'p'://print tree
printf("\n\n");
print(root);
printf("\nHeight= %i\n\n",height(root));
break;
case '?'://display help
help();
break;
default://idiot >.>
printf("Invalid input!\n\n");
help();
break;
}
}
}
return;
}
Either the largest of the nodes to the left or the smallest of the nodes to the right will take it's place!
Simply put one of these where the deleted node was (and delete them from your previous position) and your tree will still be a valid binary search tree. Take a look at this example:
15
/ \
… 25
/ \
20 30
\
23
Suppose you wanted to delete node 25:
By the properties of the binary search tree you already know that all children have to be larger than the parent (15), therefore using one of them instead of the 25 is valid. ✓
If you choose the largest node from the left sub tree (23) it will be larger than any of the nodes to the left, but it also will be smaller than any of the nodes to the right, therefore it fits nicely in the middle and can take the place of the deleted node. ✓
The same is true for the smallest node from the right sub tree (30). ✓
In case the chosen node is a leaf everything is fine and you can delete it. Otherwise perform the delete operation on your chosen node.
You can also take a look at the Wikipedia article of the binary search tree for a pseudocode implementation.
Related
This question already has an answer here:
Printing to a file in C
(1 answer)
Closed 4 years ago.
I have multiple functions that are recursive. They print multiple times the results. I need to create a file that contains all those outputs.
The functions that print are:void print_inorder,void print_preorder, void print pre_order;
EXAMPLE INPUT: 1 (case option-preorder), 1 2 3 4 5 q(the numbers that are inserted into the tree, q ends the scanf);
OUTPUT: 1 2 3 4 5, I need this to be printed into a file too.
MY code:
#include<stdlib.h>
#include<stdio.h>
#include<conio.h>
#include<time.h>
#include<pthread.h>
struct node1
{
int key1;
struct node1 *left1, *right1;
};
// A utility function to create a new BST node1
struct node1 *newnode1(int item)
{
struct node1 *temp1 = (struct node1 *)malloc(sizeof(struct node1));
temp1->key1 = item;
temp1->left1 = temp1->right1 = NULL;
return temp1;
}
// A utility function to do inorder traversal of BST
void inorder(struct node1 *root1)
{
if (root1 != NULL)
{
inorder(root1->left1);
printf("%d ", root1->key1);
inorder(root1->right1);
}
}
/* A utility function to insert1 a new node1 with given key1 in BST */
struct node1* insert1(struct node1* node1, int key1)
{
/* If the tree is empty, return a new node1 */
if (node1 == NULL) return newnode1(key1);
/* Otherwise, recur down the tree */
if (key1 < node1->key1)
node1->left1 = insert1(node1->left1, key1);
else
node1->right1 = insert1(node1->right1, key1);
/* return the (unchanged) node1 pointer */
return node1;
}
/* Given a non-empty binary search tree, return the node1 with minimum
key1 value found in that tree. Note that the entire tree does not
need to be searched. */
struct node1 * minValuenode1(struct node1* node1)
{
struct node1* current = node1;
/* loop down to find the left1most leaf */
while (current->left1 != NULL)
current = current->left1;
return current;
}
/* Given a binary search tree and a key1, this function deletes the key1
and returns the new root1 */
struct node1* deletenode1(struct node1* root1, int key1)
{
// base case
if (root1 == NULL) return root1;
// If the key1 to be deleted is smaller than the root1's key1,
// then it lies in left1 subtree
if (key1 < root1->key1)
root1->left1 = deletenode1(root1->left1, key1);
// If the key1 to be deleted is greater than the root1's key1,
// then it lies in right1 subtree
else if (key1 > root1->key1)
root1->right1 = deletenode1(root1->right1, key1);
// if key1 is same as root1's key1, then This is the node1
// to be deleted
else
{
// node1 with only one child or no child
if (root1->left1 == NULL)
{
struct node1 *temp1 = root1->right1;
free(root1);
return temp1;
}
else if (root1->right1 == NULL)
{
struct node1 *temp1 = root1->left1;
free(root1);
return temp1;
}
// node1 with two children: Get the inorder successor (smallest
// in the right1 subtree)
struct node1* temp1 = minValuenode1(root1->right1);
// Copy the inorder successor's content to this node1
root1->key1 = temp1->key1;
// Delete the inorder successor
root1->right1 = deletenode1(root1->right1, temp1->key1);
}
return root1;
}
struct bin_tree {
int data;
struct bin_tree * right, * left;
};
typedef struct bin_tree node;
void insert(node ** tree, int val)
{
node *temp = NULL;
if(!(*tree))
{
temp = (node *)malloc(sizeof(node));
temp->left = temp->right = NULL;
temp->data = val;
*tree = temp;
return;
}
if(val < (*tree)->data)
{
insert(&(*tree)->left, val);
}
else if(val > (*tree)->data)
{
insert(&(*tree)->right, val);
}
}
void print_preorder(node * tree)
{
if (tree)
{
printf("%d\n",tree->data);
print_preorder(tree->left);
print_preorder(tree->right);
}
}
void print_inorder(node * tree)
{
if (tree)
{
print_inorder(tree->left);
printf("%d\n",tree->data);
print_inorder(tree->right); // i want to print this as a tree
}
}
void print_postorder(node * tree)
{
if (tree)
{
print_postorder(tree->left);
print_postorder(tree->right);
printf("%d\n",tree->data);
}
}
void deltree(node * tree)
{
if (tree)
{
deltree(tree->left);
deltree(tree->right);
free(tree);
}
}
node* search(node ** tree, int val)
{
if(!(*tree))
{
return NULL;
}
if(val < (*tree)->data)
{
search(&((*tree)->left), val);
}
else if(val > (*tree)->data)
{
search(&((*tree)->right), val);
}
else if(val == (*tree)->data)
{
return *tree;
}
}
void main()
{
int a;
int searcharg;
int deletearg;
char option;
printf("1:PreOrder\n2:InOrder\n3:PostOrder\n4:search\n5:Delete Node\nYour Option: ");
scanf("%c", &option);
clock_t tic = clock();
node *root;
node *tmp;
//int i;
root = NULL;
struct node1 *root1 = NULL;
/* Inserting nodes into tree */
while (scanf("%d", &a) && a!='q'){insert(&root,a); root1 = insert1(root1, a);}
// these
/* Printing nodes of tree */
switch(option)
{
case '1':
printf("Pre Order Display\n");
print_preorder(root); // i want to print this as a tree
break;
case '2':
printf("In Order Display\n");
print_inorder(root); // i want to print this as a tree
break;
case '3':
printf("Post Order Display\n");
print_postorder(root); // i want to print this as a tree
break;
case '4':
scanf("%d", &searcharg);
tmp = search(&root, searcharg);
if (tmp)
{
printf("The searched node is present = %d\n", tmp->data);
}
else
{
printf("Data Not found in tree.\n");
}
break;
default:
printf("Error! operator is not correct\n");
break;
case '5':
// printf("scan");
// scanf("%d", &deletearg);
root1 = deletenode1(root1, 5);
inorder(root1);
}
// i want to print this as a tree
/* Deleting all nodes of tree */
deltree(root);
clock_t toc = clock();
printf("\nElapsed: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);
getch();
}
Solution 1: Open the file in your main function and pass file pointer as parameter into every function you need to write to the file. Close it at the end of the main function.
Solution 2: Use global variable:
FILE * g_my_file = fopen("my_file.txt", "wt");
Then instead of your printf use:
fprintf(g_my_file, "%d\n", tree->data);
Maybe close it somewhere at the end of the program/main:
fclose(g_my_file);
As this is not mentioned in other answers you can open file with proper mode
Demo
fp = fopen("file.txt","a");
//write dome data here this will be appended to the end of the file
fclose(fp);
Also this does not need global variable for file identifier
Edit:
With proper mode a in fopen, there is no need for fseek
If your are running the program on linux just type:
./a.out >> your_filename
When I try to run my program, it takes input till 2 or 3 steps and then it ends abruptly, even if I press Y for entering more elements.This is the screenshot of my output: Here's my segment of code, lc stands for left child, rc stands for right child and ht stands for height of tree:
void inorder(struct node *root) //print inorder
{
if(root->lc!=NULL)
inorder(root->lc);
printf("%d ",root->data);
if(root->rc!=NULL)
inorder(root->rc);
}
struct node *insert(struct node *T,int x) //code for insertion of a node
{
if(T==NULL)
{
T=(struct node*)malloc(sizeof(struct node));
T->data=x;
T->lc=NULL;
T->rc=NULL;
}
else
{
if(x > T->data)
{
T->rc=insert(T->rc,x);
if(BF(T)==-2)
if(x>T->rc->data)
T=RR(T);
else
T=RL(T);
}
else
{
if(x<T->data)
{
T->lc=insert(T->lc,x);
if(BF(T)==2)
if(x < T->lc->data)
T=LL(T);
else
T=LR(T);
}
}
T->ht=height(T);
return(T);
}
}
int main()
{
struct node *root=NULL;
int ele;
char ch;
do
{
printf("\n Enter the value to be inserted in AVL: ");
scanf("%d",&ele);
root=insert(root,ele);
printf("\n Want to insert more elements? (y/n): ");
getchar();
scanf("%c",&ch);
}while(ch=='y' || ch=='Y');
printf("\n Press any key to print inorder traversal: ");
getchar();
inorder(root);
return 0;
}
I am working on an algorithm to delete a node with a given key from a binary search tree. So far, I have been able to come up with the following code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
typedef int ElType;
typedef struct Tree {
ElType key;
struct Tree *left;
struct Tree *right;
struct Tree *parent;
} Tree;
Tree* InsertBST(Tree* t, int k)
{
if (t == NULL) {
Tree* w = (Tree*) malloc(sizeof(Tree));
w->key = k;
w->left = NULL;
w->right = NULL;
w->parent = NULL;
return w;
}
if (k <= t->key) {
t->left = InsertBST(t->left, k);
t->left->parent = t;
}
else {
t->right = InsertBST(t->right, k);
t->right->parent = t;
}
return t;
}
Tree* DeleteMaxOfBST(Tree* t, ElType *deleted_value)
{
if (t == NULL) {
*deleted_value = -1;
return NULL;
}
if (t->right == NULL) {
*deleted_value = t->key;
Tree* w = t->left;
w->parent = t->parent;
free(t);
return w;
}
t->right = DeleteMaxOfBST(t->right, deleted_value);
return t;
}
Tree* DeleteNodeOfBST(Tree* t, int k)
{
if (t == NULL) return NULL;
if (k < t->key) {
t->left = DeleteNodeOfBST(t->left, k);
return t;
}
else if (k > t->key) {
t->right = DeleteNodeOfBST(t->right, k);
return t;
}
else if (t->left == NULL) {
Tree* w = t->right;
w->parent = t->parent;
free(t);
return w;
}
else {
ElType max_left;
t->left = DeleteMaxOfBST(t->left, &max_left);
t->key = max_left;
return t;
}
}
The general idea is that I want to work with a BST with pointers to parent nodes and be able to delete a node with whichever key I specify while preserving the structure of a BST.
My code works for some keys in some trees but crashes for other keys without any apparent pattern. I then get the following error:
Segmentation fault (core dumped)
I am inclined to think I have messed up the pointers to the parent nodes but cannot quite pinpoint where the fault is. I am relatively new to C, so I would appreciate any comments whether pointers are in fact the problem here and how to possibly fix this.
So, without any examples of how your code runs it's hard to say where exactly the segmentation fault is occurring when your program is running. When your program encounters a segmentation fault that means that the program is attempting to access memory that, for whatever reason, it is unable to. This generally means your pointers are trying to point at an address in memory that they shouldn't be.
My suggestion would be to run the code step by step and see where the problem occurs. Or find a debugger that can show you the memory issues your program is having. I know that the program Valgrind exists for Ubuntu and other Linux best machines, but I'm not sure what others are available for other OSes. You can read more about Valgrind here: http://valgrind.org/. I use it whenever I need to check for potential memory handling issues in my programs.
Other than that, just keep a real close eye on the space that you create using malloc, as well as where your pointers are pointing. Make sure to reconnect your tree properly when you delete the given node. Manually handling memory can be a pain, but you'll get the hang of it.
Here is the source code for C Program for Insertion and Deletion in Binary Search Tree Recursive..................
/* C Program for Insertion and Deletion in Binary Search Tree Recursive */
#include<stdio.h>
#include<stdlib.h>
struct node
{
struct node *lchild;
int info;
struct node *rchild;
};
struct node *insert(struct node *ptr, int ikey);
void display(struct node *ptr,int level);
struct node *del(struct node *ptr, int dkey);
int main( )
{
struct node *root=NULL,*ptr;
int choice,k;
while(1)
{
printf("\n");
printf("1.Insert\n");
printf("2.Delete\n");
printf("3.Display\n");
printf("4.Quit\n");
printf("\nEnter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("Enter the key to be inserted : ");
scanf("%d",&k);
root = insert(root, k);
break;
case 2:
printf("Enter the key to be deleted : ");
scanf("%d",&k);
root = del(root,k);
break;
case 3:
display(root,0);
break;
case 4:
exit(1);
default:
printf("\nWrong choice\n");
}/*End of switch */
}/*End of while */
return 0;
}/*End of main( )*/
struct node *insert(struct node *ptr, int ikey )
{
if(ptr==NULL)
{
ptr = (struct node *) malloc(sizeof(struct node));
ptr->info = ikey;
ptr->lchild = NULL;
ptr->rchild = NULL;
}
else if(ikey < ptr->info) /*Insertion in left subtree*/
ptr->lchild = insert(ptr->lchild, ikey);
else if(ikey > ptr->info) /*Insertion in right subtree */
ptr->rchild = insert(ptr->rchild, ikey);
else
printf("\nDuplicate key\n");
return ptr;
}/*End of insert( )*/
void display(struct node *ptr,int level)
{
int i;
if(ptr == NULL )/*Base Case*/
return;
else
{
display(ptr->rchild, level+1);
printf("\n");
for (i=0; i<level; i++)
printf(" ");
printf("%d", ptr->info);
display(ptr->lchild, level+1);
}
printf("\n");
}/*End of display()*/
struct node *del(struct node *ptr, int dkey)
{
struct node *tmp, *succ;
if( ptr == NULL)
{
printf("dkey not found\n");
return(ptr);
}
if( dkey < ptr->info )/*delete from left subtree*/
ptr->lchild = del(ptr->lchild, dkey);
else if( dkey > ptr->info )/*delete from right subtree*/
ptr->rchild = del(ptr->rchild, dkey);
else
{
/*key to be deleted is found*/
if( ptr->lchild!=NULL && ptr->rchild!=NULL ) /*2 children*/
{
succ=ptr->rchild;
while(succ->lchild)
succ=succ->lchild;
ptr->info=succ->info;
ptr->rchild = del(ptr->rchild, succ->info);
}
else
{
tmp = ptr;
if( ptr->lchild != NULL ) /*only left child*/
ptr = ptr->lchild;
else if( ptr->rchild != NULL) /*only right child*/
ptr = ptr->rchild;
else /* no child */
ptr = NULL;
free(tmp);
}
}
return ptr;
}/*End of del( )*/
Hope it may help you. For more details, Visit here for More Operations on Binary Search tree ---> C Program for Insertion and Deletion in Binary Search Tree Recursive
and C Program for binary search tree deletion without recursion
I'm almost finished with my Binary Search Tree program. However, I'm stuck at deletion: removing a node with both left and right subtrees. The largest left value is promoted in the left subtree. It sometimes works, but does not always work the way it should be. Ie, if you input values 23, 14, 31, 7, 9 into the tree and remove 23, the values that come out are 14 14 7 9. Please help!
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int key;
struct node* left;
struct node* right;
}node;
struct node* root= NULL;
int count=0;
void preOrder(node* temp){
if (temp!=NULL){
printf("%d ",temp->key);
preOrder(temp->left);
preOrder(temp->right);
}
}
//for printing
void inOrder(node* temp){
if (temp!=NULL){
inOrder(temp->left);
printf("%d ",temp->key);
inOrder(temp->right);
}
}
void printPrompt(void){
int choice=-1;
do{
printf(" Enter <1> Inorder <2> Preorder <3> Return to Menu: ");
scanf("%d", &choice);
if(choice!=1 && choice!=2 && choice!=3) printf(" Error: invalid input! \n\n");
if(choice==1){
if(root==NULL) printf("\tError: is empty tree\n");
else {
printf("\tInorder:\t ");
inOrder(root);
printf("\n\n");
}
}
else if (choice==2){
struct node* temp=root;
if(root==NULL) printf("\tError: is empty tree\n");
else {
printf("\tPreorder:\t ");
preOrder(root);
printf("\n\n");
}
}
}while (choice!=3);
printf(" <Exit print method>\n\n");
}
//printing complete
//both are similar code- one searches and another finds the node
int contains(node* current, int value){
if(current==NULL) return 0;
if (value==current->key) {
return 1;
}
else if(value < current->key) return contains(current->left, value);
else return contains(current->right, value);
}
node* findParent(node* current, int value){
if (value == current->key) return NULL; //if only one node in BST, then no parent node
if (value < current->key) {
if (current->left == NULL) return NULL; //if value not found, return null
else if (current->left->key == value) return current;
else return findParent (current->left, value);
}
else {
if (current->right == NULL) return NULL;
else if (current->right->key== value) return current;
else return findParent (current->right, value);
}
}
node* findNode(node* current, int value){
if (current == NULL) return NULL;
if (current->key == value) {
return current;
}
else if (value < current->key) return findNode (current->left, value);
else return findNode (current->right, value);
}
//
void del(value){
struct node* nodeToRemove= findNode(root, value);
if (nodeToRemove == NULL) printf("\tError: node not found in tree\n");
else {
struct node* parent = findParent(root, value);
if (count == 1 ) {
root= NULL;
printf("\tRemoving the only node in BST\n");
}
else if (nodeToRemove->left == NULL && nodeToRemove->right == NULL){
printf("\tRemoving leaf node in BST\n");
if (nodeToRemove->key < parent->key) parent->left = NULL;
else parent->right = NULL;
}
else if (nodeToRemove->left== NULL && nodeToRemove->right != NULL){
printf("\tRemoving node with right subtree but no left subtree\n");
if (nodeToRemove->key < parent->key) {
parent->left = nodeToRemove->right;
}
else parent->right = nodeToRemove->right;
}
else if (nodeToRemove->left!= NULL && nodeToRemove->right == NULL){
printf("\tRemoving node with left subtree but no right subtree\n");
if (nodeToRemove->key < parent->key) {
parent->left = nodeToRemove->left;
}
else parent->right = nodeToRemove->left;
}
else{
printf("\tRemoving node with both left subtree and right subtree\n");
struct node* nodeLargestLeft = nodeToRemove -> left;
while (nodeLargestLeft -> right != NULL) nodeLargestLeft= nodeLargestLeft->right;
findParent(root, nodeLargestLeft->key)->right=NULL;
nodeToRemove->key=nodeLargestLeft->key;
}
}
printf("\tResult: ");
preOrder(root);
printf("\n");
count= count-1;
}
void deletePrompt(void){
int value=-1;
do{
printf(" Delete key or press -1 to return to menu: ");
scanf("%d", &value);
if(value>0){
if(root==NULL) printf("\tError: is empty tree\n");
else del(value);
}
else if (value<=0) printf("\tError: key not positive\n");
}while (value!=-1);
printf(" <Exit delete method>\n\n");
}
void searchPrompt(void){
int value=-1;
do{
printf(" Search key or press -1 to return to menu: ");
scanf("%d", &value);
if(value>0){
if (root==NULL) printf("\tError: tree is empty\n");
else {
if(contains(root, value)) printf("\tKey %d is found\n",value);
else printf("\tKey %d is not found\n",value);
}
}
else if (value<=0) printf("\tError: key not positive\n");
}while (value!=-1);
printf(" <Exit search method>\n\n");
}
//for search
//for insertion
void insertNode(node* current, int value){
if(value< current->key){
if (current->left == NULL) {
current->left=(node*) malloc(sizeof(node));
current->left->key = value;
current->left->left = NULL;
current->left->right = NULL;
printf("\tSuccess! Value inserted: %d\n", current->left->key);
}
else {
insertNode(current->left, value);
}
}
else {
if (current->right == NULL) {
current->right=(node*) malloc(sizeof(node));
current->right->key = value;
current->right->left = NULL;
current->right->right = NULL;
printf("\tSuccess! Value inserted: %d\n", current->right->key);
}
else {
insertNode(current->right, value);
}
}
}//end insert
void insert(int value){
if(root==NULL){ //empty tree
root =(node*) malloc(sizeof(node));
root->key= value;
printf("\tPrint root here: %d\n", value);
root->left= NULL;
root->right=NULL;
printf("\tSuccess! Value inserted: %d\n", root->key);
}
else {
insertNode(root, value);
}
printf("\tResult: ");
preOrder(root);
printf("\n");
}
void insertPrompt(void){
int value=-1;
do{
printf(" Insert value or press -1 to return to menu: ");
scanf("%d", &value);
if(value>0){
insert(value);
count= count+1;
printf("\tCount: %d\n", count);
}
else if (value<=0)printf("\tError: key not positive\n");
}while (value!=-1);
printf(" <Exit insert method>\n\n");
}
int menuPrompt(void){
int choice=-1;
do{
printf("Enter <1> Search <2> Insert <3> Delete <4> Print Tree <5> Quit: ");
scanf("%d", &choice);
if(choice>5 || choice<1) printf("Error: invalid input! \n\n");
} while(choice>5 || choice<1);
return choice;
}
int main(int argc, char *argv[]){
int choice=-1;
int value=-1;
while(choice!=5){
choice=menuPrompt();
switch(choice){
case 1:
searchPrompt();
break;
case 2:
insertPrompt();
break;
case 3:
deletePrompt();
break;
case 4:
printPrompt();
break;
case 5:
printf("<Exit program> \n");
break;
}//end switch
}
system("PAUSE");
return 0;
}
Your deletion algorithm for a node with two subtrees is slightly wrong. What you are correctly doing is:
Find the maximum of the left subtree (or minimum of the right subtree):
struct node* nodeLargestLeft = nodeToRemove -> left;
while (nodeLargestLeft -> right != NULL)
nodeLargestLeft= nodeLargestLeft->right;
Replace the value of the node to be removed with the value of the node found above
nodeToRemove->key=nodeLargestLeft->key;
You try to delete 23 from your example tree
23
/ \
14 31
/
7
\
9
which has 14 as largest value in the left subtree and now looks like this:
14
/ \
14 31
/
7
\
9
But now, you can't just delete the the right subtree of the parent of the largest node (which is your root node). This would be the right subtree of your whole binary tree in the example case you mention!
findParent(root, nodeLargestLeft->key)->right=NULL; // wrong
Instead you have to do a regular deletion procedure for the duplicate node (the node 14 in the second level). Since it was the node with the largest value in the left subtree it cannot have a right subtree. So there are only two cases: Either, the left subtree is empty too, in which case the node can be discarded, or it is populated, in which case the root node of the left subtree replaces this node.
In your example the second case occurs and your tree should then look like that:
14
/ \
7 31
\
9
With minimal intrusive changes this procedure should work:
printf("\tRemoving node with both left subtree and right subtree\n");
struct node* nodeLargestLeft = nodeToRemove->left;
parent = findParent(root, nodeLargestLeft->key);
while (nodeLargestLeft -> right != NULL) {
parent = nodeLargestLeft;
nodeLargestLeft= nodeLargestLeft->right;
}
nodeToRemove->key=nodeLargestLeft->key;
parent->left = nodeLargestLeft->left;
Your code has several other issues, for example
when deleting the root node with only a left or a right subtree, parent is a NULL-pointer, leading to a segfault on parent->key
duplicates are inconsistently handled
many code paths can be merged to a single one, eliminating redundancy and enhancing code readability
the calls to findParent look ugly, better track the parent while traversing the tree or maintaining a parent-pointer for each node.
Okay I solved my own problem. There was a special case.
else{
printf("\tRemoving node with both left subtree and right subtree\n");
//special case, if left of nodeToRemove has no right node
struct node* nodeLargestLeft = nodeToRemove -> left;
if (nodeToRemove->left->right == NULL) {
nodeToRemove->key = nodeToRemove->left ->key;
nodeToRemove->left = nodeToRemove->left->left;
}else{
while (nodeLargestLeft -> right != NULL) nodeLargestLeft= nodeLargestLeft->right;
findParent(root, nodeLargestLeft->key)->right=NULL;
nodeToRemove->key=nodeLargestLeft->key;
}
}
DELETION is the most perverse routine in a b-tree this is mine,
and this is the wiki article that resume what I did https://en.wikipedia.org/wiki/Binary_search_tree#Deletion
void bt_rec_delete(pbbtree bt, size_t root)
{
ptbBtreeNode me, right, left, parent, replacer;
char side;
ll rec;
me = &bt->tb[root];
me->deleted = TRUE;
right = me->right == 0 ? NULL : &bt->tb[me->right];
left = me->left == 0 ? NULL : &bt->tb[me->left];
parent = me->parent == 0 ? NULL : &bt->tb[me->parent];
// if (parent)
// disp_dbt(bt,parent->index,0);
if (parent)
side = parent->right == root ? 'r' : 'l';
else
side = 0;
if (!right && !left)
{
if (side == 'r')
parent->right = 0;
else if (side == 'l')
parent->left = 0;
else
bt->current_root = 0;
propagate_depth(bt, root);
}
else if (!right)
{
left->parent = me->parent;
if (side == 'r')
parent->right = left->index;
else if (side == 'l')
parent->left = left->index;
else
bt->current_root = left->index;
propagate_depth(bt, left->index);
}
else if (!left)
{
right->parent = me->parent;
if (side == 'r')
parent->right = right->index;
else if (side == 'l')
parent->left = right->index;
else
bt->current_root = right->index;
propagate_depth(bt, right->index);
}
else
{
unsigned rec_par;
if (right->depth > left->depth)
{
rec = bt_get_maximum(bt, right->index);
assert(rec > 0);
rec_par = bt->tb[rec].parent;
if (rec_par != me->index)
{
bt->tb[rec_par].left = bt->tb[rec].right; // maximum assure me there is no left leaf
if (bt->tb[rec].right > 0)
bt->tb[bt->tb[rec].right].parent = rec_par;
bt->tb[rec].right = 0;
}
propagate_depth(bt, rec_par);
}
else
{
rec = bt_get_minimum(bt, left->index);
assert(rec > 0);
rec_par = bt->tb[rec].parent;
if (rec_par != me->index)
{
bt->tb[rec_par].right = bt->tb[rec].left;// minimum assure me there is no right leaf
if (bt->tb[rec].left > 0)
bt->tb[bt->tb[rec].left].parent = rec_par;
bt->tb[rec].left = 0;
}
propagate_depth(bt, rec_par);
}
replacer = &bt->tb[rec];
replacer->depth = me->depth;
if (side == 'r')
parent->right = replacer->index;
else if (side == 'l')
parent->left = replacer->index;
else
bt->current_root = replacer->index;
replacer->parent = me->parent;
if (replacer->index != left->index)
{
replacer->left = left->index;
left->parent = replacer->index;
}
if (replacer->index != right->index)
{
replacer->right = right->index;
right->parent = replacer->index;
}
}
}
So, here i have come up with Binary search tree prgram, where i am creating 2 binary trees tmp and tmp2, where i am trying to copy whole tmp2 to tmp, the node which is taken as input from user. But i am getting some segmentation fault, also i am not so sure if the logic is right.
Here is the whole program, please lemme know where is it going wrong in t_cpy() or please just fix it for me..
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *rlink;
struct node *llink;
}*tmp=NULL,*tmp2=NULL,*tmp3=NULL;
typedef struct node NODE;
NODE *create();
void inorder(NODE *);
void insert(NODE *);
void t_cpy(NODE *,NODE *);
int main()
{
int n,m;
do
{
printf("\n1.create tree 1\n2.Insert element to tree1\n3.create tree 2\n4.Insert element to tree2\n5.Inorder tree1\n6.Inorder tree2\n7.Copy tree2 to tree1\n8.exit\n\n");
printf("\nEnter ur choice: ");
scanf("%d",&m);
switch(m)
{
case 1: tmp=create();
break;
case 2: insert(tmp);
break;
case 3: tmp2=create();
break;
case 4:
insert(tmp2);
break;
case 5: printf("\n\nInorder Tree1: ");
inorder(tmp);
break;
case 6: printf("\n\nInorder Tree 2: ");
inorder(tmp2);
break;
case 7: t_cpy(tmp,tmp2);
break;
case 8: return(0);
}
}while(n!=8);
return(0);
}
void insert(NODE *root)
{
NODE *newnode;
if(root==NULL)
{
newnode=create();
root=newnode;
}
else
{
newnode=create();
while(1)
{
if(newnode->data<root->data)
{
if(root->llink==NULL)
{
root->llink=newnode;
break;
}
root=root->llink;
}
if(newnode->data>root->data)
{
if(root->rlink==NULL)
{
root->rlink=newnode;
break;
}
root=root->rlink;
}
}
}
}
NODE *create()
{
NODE *newnode;
int n;
newnode=(NODE *)malloc(sizeof(NODE));
printf("\n\nEnter the Data ");
scanf("%d",&n);
newnode->data=n;
newnode->llink=NULL;
newnode->rlink=NULL;
return(newnode);
}
void t_cpy(NODE *t1,NODE *t2)
{
int val,opt=0;
NODE *temp;
if(t1==NULL || t2==NULL)
{
printf("Can not copy !\n");
}
inorder(t1);
printf("\nEnter the node value where tree 2 should be copied\n");
scanf("%d",&val);
temp=t1;
while(temp!=NULL)
{
if(val<temp->data)
temp=temp->llink;
else
temp=temp->rlink;
}
if(temp->llink!=NULL || temp->rlink!=NULL)
printf("Not possible to copy tree to this node\n");
else
{
printf("Copy tree to \n 1.Left Node \n 2.Right Node\n Enter your choice : ");
scanf("%d",&opt);
if(opt==1)
{
temp->llink=t2;
}
else if(opt==2)
{
temp->rlink=t2;
}
else
printf("Invalid choice\n");
}
printf("Tree1 after copying is\n");
inorder(temp);
}
void inorder(NODE *tmp)
{
if(tmp!=NULL)
{
inorder(tmp->llink);
printf("%d",tmp->data);
inorder(tmp->rlink);
}
}
EDIT : Thanks to #xaxxon , who helped me with this.
Just update the while to make it work :
while(temp!=NULL&&temp->data!=val)
{
if(val<temp->data)
temp=temp->llink;
else
temp=temp->rlink;
if(temp->llink==NULL && temp->rlink==NULL && temp->data!=val)
{
printf("Invalid Node value entered !\n");
//break;
return 0;
}
and, Now it works fine for if entered value is present in the tree.
Thanks :)
Among other possible problems, you traverse temp until it is null, and on the next line you dereference it.
while(temp!=NULL)
{
if(val<temp->data)
temp=temp->llink;
else
temp=temp->rlink;
}
if(temp->llink!=NULL || temp->rlink!=NULL)
printf("Not possible to copy tree to this node\n");
You most likely mean to break out of this loop if val == temp->data, but you don't. Also, you still need to check to see if temp is null after the loop in case you didn't find val in your tree. Most likely you just meant to say:
if(temp==NULL)
printf("Not possible to copy tree to this node\n");
Also, you can't ask which side of the found node the user wants to copy a tree to. If you have a binary search tree, it has to be the side where the value should go. If you say to copy it to the right side, but all the values are less than the node, it's no longer a BST. In fact, you can't even ask where the value should go and still have a binary search tree. Each node has to be traversed from the root of the tree you want to put the other tree into to maintain the BST mechanics.
When you first use insert(tmp) the value of tmp does not change after you call insert(). Pass the address of tmp to insert(), using a *root within it instead of root.