Inaccuracy in output of deletion function in binary search tree - data-structures

I am making a binary search tree code, in that 'am facing an issue in the deletion function. After executing the function, the code is showing inorder display incorrectly. Basically, it is incorrect, and I'am not able to understand where the problem is.
In the delete function, I have used a search function that will find the node which the user has to delete. And I have used inorder successor method for deletion so the minimum function will find the successor. All other functions like insertion, minimum, and inorder are working fine.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *left;
struct node *right;
} node;
struct node *insert(struct node *tnode, int data)
{
if (tnode == NULL)
{
struct node *ptr;
ptr = (struct node *)malloc(sizeof(struct node));
ptr->data = data;
ptr->left = NULL;
ptr->right = NULL;
return ptr;
}
if (data > (tnode->data))
{
tnode->right = insert(tnode->right, data);
return tnode;
}
if (data < (tnode->data))
{
tnode->left = insert(tnode->left, data);
return tnode;
}
}
void in_order(struct node *tnode)
{
if (tnode == NULL)
return;
else
{
in_order(tnode->left);
printf("%d\t", tnode->data);
in_order(tnode->right);
}
}
struct node *search(struct node *tnode, int data)
{
if (tnode == NULL)
{
return NULL;
}
else
{
if (data == tnode->data)
{
return tnode;
}
else
{
if (data > tnode->data)
{
search(tnode->right, data);
}
else
{
search(tnode->left, data);
}
}
}
}
struct node *minimum(struct node *tnode)
{
if (tnode == NULL)
{
printf("No node present\n");
return NULL;
}
else
{
if (tnode->left == NULL)
return tnode;
else
minimum(tnode->left);
}
}
struct node *deletenode(struct node *tnode, int data)
{
struct node *s;
s = search(tnode, data);
if (s == NULL)
{
printf("Value not found\n");
return NULL;
}
else
{
if (s->left == NULL && s->right == NULL) // No child case
{
free(s);
return NULL;
}
else
{
if (s->left == NULL && s->right != NULL) // single child case(right child)
{
struct node *temp = s->right;
free(s);
return temp;
}
else if (s->right == NULL && s->left != NULL) // single child case(left child)
{
struct node *temp = s->left;
free(s);
return temp;
}
else
{
struct node *temp;
temp = minimum(s->right);
s->data = temp->data;
s->right = deletenode(s->right, temp->data);
}
}
}
return s;
}
int main()
{
struct node *root = NULL, *del;
int n, i, data, key;
printf("Enter how many nodes you have to enter in a tree\n");
scanf("%d", &n);
for (i = 0; i < n; i++)
{
printf("Enter data\n");
scanf("%d", &data);
root = insert(root, data);
}
printf("\nIN-Order display\n");
in_order(root);
int d;
printf("\nEnter data to be delete\n");
scanf("%d", &d);
del=deletenode(root, d);
printf("\nIN-Order display\n");
in_order(root);
return 0;
}

There are several places missing return (in minimum, search and deletenode). You can easily find them if you compile with -Wall -Wextra compiler options.
It is not clear, what do you want to return from deletenode. I assume that it is a tree with deleted element. Then either search should return a parent node (so it is possible to change pointers to freed node), or deletenode should move to parent node.
Also, use in_order(del) instead of in_order(root) because root can be changed while deleting.

Related

preorder traversal using stack

i'm trying to implement binary tree, pre order traversal using stack.
here its popping the last left node and after that root=root->right doesnt seem to work. Pls help. here 7 is being popped out and is being displayed and after the the program is ending.
all the functions are working yet not the desired output
#include<stdio.h>
#include<stdlib.h>
#define maxsize 100
int a[maxsize];
int top=-1;
struct node{
int data;
struct node *left, *right;
};
struct node *newNode(int data)
{
struct node *nn;
nn=(struct node *)malloc(sizeof(struct node));
if(!nn)
return;
nn->data=data;
nn->left=nn->right=NULL;
return nn;
};
void push(struct node *root)
{
printf("pushcalled\n");
if(top!=maxsize-1)
a[++top]=root;
}
int isempty()
{
return(top==-1);
}
struct node *pop()
{
printf("popcalled\n");
if(top!=-1)
{
return a[top];
top--;
}
}
void deleteStack()
{
free(a[top--]);
}
void preorder(struct node *root)
{
while(1)
{
while(root)
{
printf("%d\t",root->data);
push(root);
root=root->left;
}
printf("hello\n");
if(isempty())
break;
printf("hello\n");
root=pop();
printf("Popped data is:%d\n",root->data);
root=root->right;
printf("right data is:%d\n",root->data);
}
deleteStack();
}
int main()
{
int data;
struct node *root=newNode(10);
root->left = newNode(11);
root->left->left = newNode(7);
root->right = newNode(9);
root->right->left = newNode(15);
root->right->right = newNode(8);
preorder(root);
return 0;
}
Your logic is correct but there are some errors in your code.
root=root->right;
printf("right data is:%d\n",root->data);
you should check whether the root is null or not before you try to access root->data. That is why you are getting a segmentation fault. So put a condition if(root!=NULL) above printf() statement.
Another mistake is in the implementation of stack's pop.
struct node *pop()
{
printf("popcalled\n");
if(top!=-1)
{
return a[top];
top--;
}
}
it should be like this,
struct node *pop()
{
printf("popcalled\n");
if(top!=-1)
{
struct node* temp = a[top];
top--;
return temp;
}
}
In your code, when you return a[top]; the line below it i.e. top--; never executes and the value of top remains same.

Doubly Linked List insert function

I am having problem with this code.Can someone help me to fix it ?
Problem is in insert function especially with malloc(allocating).I don't understand why I cannot malloc.It is not printing the debug text.
#include<stdlib.h>
#include<stdio.h>
#define TRUE 1
#define FALSE 0
struct Node{
int data;
struct Node* next;
struct Node* prev;
};
struct ListRecord
{
struct Node *head;
struct Node *tail;
int length;
};
typedef struct ListRecord *DoubleList;
DoubleList createList()
{
return NULL;
}
DoubleList MakeEmptyList(DoubleList l)
{
l = (struct ListRecord*)malloc(sizeof(struct ListRecord));
if(l==NULL)
{
printf("Memory allocation failed!");
}
else
{
l->head->next=NULL;
l->head->prev=NULL;
l->tail=l->head;
l->length=0;
}
}
DoubleList InsertListAtPosition(DoubleList l,int pos,int val)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
printf("debug");
if(newNode==NULL)
{
printf("debug");
newNode->data=val;
newNode->next=NULL;
newNode->prev=NULL;
if(pos > l->length+1)
{
pos=l->length+1;
}
else if(pos==l->length+1)
{
struct Node *iterator=l->head;
while(iterator->next != NULL)
{
iterator=iterator->next;
}
iterator->next=newNode;
newNode->prev=iterator;
newNode->next=NULL;
}
else
{
struct Node* iterator=l->head;
int i;
for(i=0;i<pos;i++)
iterator=iterator->next;
newNode->next=iterator->next;
newNode->prev=iterator;
iterator->next->prev=newNode;
iterator->next=newNode;
}
l->length++;
}
else
{
printf("Memory allocation failed!");
}
}
int DeleteListAtPosition(DoubleList l,int pos)
{
int value;
if(l==NULL)
{
printf("List is empty");
return 0;
}
else
{
if(pos==1)
{
struct Node* iterator=l->head;
value=iterator->data;
free(iterator);
return value;
}
else
{
struct Node* iterator=l->head;
int i;
for(i=1;i<pos;i++)
iterator=iterator->next;
if(iterator->next==NULL)
{
value=iterator->data;
free(iterator);
return value;
}
else
{
iterator->prev->next=iterator->next;
iterator->next->prev=iterator->prev;
free(iterator);
}
}
}
}
void printList(DoubleList l) {
struct Node* temp = l->head;
printf("Forward: ");
while(temp != NULL) {
printf("%d ",temp->data);
temp = temp->next;
}
printf("\n");
}
int main(){
DoubleList myList;
int exit,pos,value;
char command;
myList=createList();
exit=FALSE;
while(!exit)
{
fflush(stdin);
printf("\nMenu:\n m)akeEmpty\n i)nsert\n e)xit\n");
scanf("%c", &command);
fflush(stdin);
switch(command)
{
case 'm':
myList = MakeEmptyList(myList);
break;
case 'i':
printf("Enter position to be added: ");
scanf("%d",&pos);
printf("Enter value to be added: ");
scanf("%d",&value);
InsertListAtPosition(myList,pos,value);
//printList(myList);
break;
case 'e':
exit = TRUE;
break;
default:
printf("command not recognized\n");
break;
}
}
printf("\n\n");
system("PAUSE");
return 0;
}
Here is the working code,
#include<stdlib.h>
#include<stdio.h>
#include <bits/stdc++.h>
#define TRUE 1
#define FALSE 0
using namespace std;
struct Node{
int data;
struct Node* next;
struct Node* prev;
};
struct ListRecord
{
struct Node *head;
struct Node *tail;
int length;
};
typedef struct ListRecord *DoubleList;
DoubleList createList()
{
return NULL;
}
DoubleList MakeEmptyList()
{
DoubleList l;
l = (struct ListRecord*)malloc(sizeof(struct ListRecord));
if(l==NULL)
{
printf("Memory allocation failed!");
}
else
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->next = NULL;
newNode->prev = NULL;
l->head = newNode;
l->tail=l->head;
l->length=0;
}
return l;
}
DoubleList InsertListAtPosition(DoubleList l,int pos,int val)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if(newNode != NULL)
{
newNode->data=val;
newNode->next=NULL;
newNode->prev=NULL;
if(pos > l->length)
{
pos=l->length+1;
}
else if(pos==l->length)
{
struct Node *iterator=l->head;
while(iterator->next != NULL)
{
iterator=iterator->next;
}
iterator->next=newNode;
newNode->prev=iterator;
newNode->next=NULL;
}
else
{
struct Node* iterator=l->head;
int i;
for(i=0;i<pos;i++)
iterator=iterator->next;
newNode->next=iterator->next;
newNode->prev=iterator;
iterator->next->prev=newNode;
iterator->next=newNode;
}
l->length++;
}
else
{
printf("Memory allocation failed!");
}
}
int DeleteListAtPosition(DoubleList l,int pos)
{
int value;
if(l==NULL)
{
printf("List is empty");
return 0;
}
else
{
if(pos==1)
{
struct Node* iterator=l->head;
value=iterator->data;
free(iterator);
return value;
}
else
{
struct Node* iterator=l->head;
int i;
for(i=1;i<pos;i++)
iterator=iterator->next;
if(iterator->next==NULL)
{
value=iterator->data;
free(iterator);
return value;
}
else
{
iterator->prev->next=iterator->next;
iterator->next->prev=iterator->prev;
free(iterator);
}
}
}
}
void printList(DoubleList l) {
struct Node* temp = l->head;
printf("Forward: ");
while(temp != NULL) {
printf("%d ",temp->data);
temp = temp->next;
}
printf("\n");
}
int main(){
DoubleList myList;
int exit,pos,value;
char command;
exit=FALSE;
while(!exit)
{
fflush(stdin);
printf("\nMenu:\n m)akeEmpty\n i)nsert\n e)xit\n");
scanf("%c", &command);
fflush(stdin);
switch(command)
{
case 'm':
myList = MakeEmptyList();
break;
case 'i':
printf("Enter position to be added: ");
scanf("%d",&pos);
printf("Enter value to be added: ");
scanf("%d",&value);
if(myList == NULL) {
myList = MakeEmptyList();
}
InsertListAtPosition(myList,pos,value);
//printList(myList);
break;
case 'e':
exit = TRUE;
break;
default:
printf("command not recognized\n");
break;
}
}
printf("\n\n");
system("PAUSE");
return 0;
}
So you were making the following mistakes,
Your MakeEmptyList method is returning nothing, it should return l.
Inside you insert you were checking with length + 1, instead of only length, so it was causing pointer related errors.

Insertion in BST

I was doing a problem on insertion. This is the right answer.
/*
Node is defined as
typedef struct node
{
int data;
node * left;
node * right;
}node;
*/
node * insert(node * root, int value)
{
if(root == NULL)
{
node *temp = new node();
temp->left = NULL;
temp->right = NULL;
temp->data = value;
root = temp;
return root;
}
if(value > root->data)
{
root->right = insert(root->right, value);
}
else
root->left = insert(root->left, value);
return root;
}
The only difference with the solution I made is that in the if/else statements I did not assign anything. This is my code.
Node is defined as
typedef struct node
{
int data;
node * left;
node * right;
}node;
*/
node * insert(node * root, int value)
{
if(root == NULL)
{
node *temp = new node();
temp->left = NULL;
temp->right = NULL;
temp->data = value;
root = temp;
return root;
}
if(value > root->data)
{
insert(root->right, value);
}
else
insert(root->left, value);
return root;
}
I am not sure I understand why this is necessary because basically calling this function recursively will find a right place for the node with the data value.
Then, I create node with right data and just insert it there.
I will leave a link to the problem. https://www.hackerrank.com/challenges/binary-search-tree-insertion
Thanks for help!

Binary Search Tree Traversals

I have just started learning Binary Trees and went ahead and tried to implement my own in C. I am kinda lost as to why only InOrder Traversal is displaying correctly while the other two are wrong. I really can't figure this out. I even directly tried inserting nodes, and the result is the same.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct Node
{
int val;
struct Node *left;
struct Node *right;
};
//Allocate Memory for New Node
struct Node* getNewNode(int val)
{
struct Node * ptr = (struct Node*)malloc(sizeof(struct Node));
ptr->val = val;
ptr->left = NULL;
ptr->right = NULL;
return ptr;
}
//Insert Node in Binary Search Tree
struct Node* insertNode(struct Node* root,int val)
{
if(root == NULL)
{
root = getNewNode(val);
}
else if(val <= root->val)
{
root->left = insertNode(root->left,val);
}
else
{
root->right = insertNode(root->right,val);
}
return root;
}
void printInorder(struct Node* root)
{
if(root == NULL) return;
printInorder(root->left);
printf("%d ",root->val);
printInorder(root->right);
}
void printPostOrder(struct Node* root)
{
if(root == NULL) return;
printInorder(root->left);
printInorder(root->right);
printf("%d ",root->val);
}
void printPreOrder(struct Node*root)
{
if(root == NULL) return;
printf("%d ",root->val);
printInorder(root->left);
printInorder(root->right);
}
bool search(struct Node* root,int val)
{
if(root == NULL)
{
return false;
}
else if(val == root->val)
{
return true;
}
else if(val < root->val)
{
return search(root->left,val);
}
else
{
return search(root->right,val);
}
}
int main(void)
{
struct Node * root = NULL; //Tree is Empty
root = insertNode(root,15);
root = insertNode(root,10);
root = insertNode(root,8);
root = insertNode(root,12);
root = insertNode(root,20);
root = insertNode(root,17);
root = insertNode(root,25);
printf("Printing In-Order: \n");
printInorder(root);
printf("\nPrinting Post-Order: \n");
printPostOrder(root);
printf("\nPrinting Pre-Order: \n");
printPreOrder(root);
// if(search(root,11))
// {
// printf("\nValue Found\n");
// }
// else
// {
// printf("\nValue Not Found\n");
// }
return 0;
}
Please help me understand if I am doing this wrong or my understanding of traversals is faulty.
The output is as follows:
output terminal
You have copy-paste errors in printPostOrder and printPreOrder - they both call printInorder where they should be calling themselves.

Trying to insert an Avl tree

I am trying to make an insertion method for an Avl tree but the structure and order of my nodes turns out to be incorrect. I am having trouble finding where i am going wrong.
Here are my methods
Any sort of help would be appreciated
template
void AvL<T>::insert(string val, T k)
{
if (head == NULL) {
head = new AvLNode<T>(val, k);
} else {
put(head, val, k);
}
}
template <class T>
void AvL<T>::put(AvLNode<T>* root,string val,T key1) {
if (root->key > key1) {
if (root->left != NULL) {
put(root->left, val, key1);
Balance(root, key1);
} else {
root->left = new AvLNode<T>(val, key1);
root->bf = nodeHeight(root->left) - nodeHeight(root->right);
root->left->parent = root;
}
} else {
if (root->right != NULL) {
put(root->right, val, key1);
Balance(root, key1);
} else {
root->right = new AvLNode<T>(val, key1);
root->bf = nodeHeight(root->left) - nodeHeight(root->right);
root->right->parent = root;
}
}
}
template<class T>
void AvL<T>::Balance(AvLNode<T>* root, T key1)
{ root->bf = nodeHeight(root->left) - nodeHeight(root->right);
if (root->bf < -1 && key1 > root->right->key) {
cout << "here1 ";
LeftRotate(root);
} else if (root->bf > 1 && key1 < root->left->key) {
cout << "here2 ";
RightRotate(root);
} else if (root->bf < -1 && key1 < root->right->key) {
RightRotate(root->right);
cout << "here3 ";
LeftRotate(root);
} else if (root->bf > 1 && key1 > root->left->key) {
LeftRotate(root->left);
cout << "here4 ";
RightRotate(root);
}
}
template<class T>
void AvL<T>::RightRotate(AvLNode<T>* node)
{
AvLNode<T>* node1 = node->left;
node->left = node1->right;
node1->right = node;
node->bf = nodeHeight(node->left) - nodeHeight(node->right);
node1->bf = nodeHeight(node1->left) - nodeHeight(node1->right);
node = node1;
}
template<class T>
void AvL<T>::LeftRotate(AvLNode<T>* node)
{
AvLNode<T>* node1 = node->right;
node->right = node1->left;
node1->left = node;
node->bf = nodeHeight(node->left) - nodeHeight(node->right);
node1->bf = nodeHeight(node1->left) - nodeHeight(node1->right);
node = node1;
}
template<class T>
int AvL<T>::nodeHeight( AvLNode<T> *n)
{
int lheight=0;
int rheight=0;
int h = 0;
if (n == NULL)
{
return -1;
} else {
lheight = nodeHeight(n->left);
rheight = nodeHeight(n->right);
h = 1+max(lheight,rheight);
return h;
}
}
My .h file
template <class T>
struct AvLNode
{
string value;
T key;
AvLNode *parent; // pointer to parent node
AvLNode *left; // pointer to left child
AvLNode *right; // pointer to right child
int bf; // Balance factor of node
AvLNode(string Val, T k)
{
this->value = Val;
this->key = k;
this->parent = NULL;
this->left = NULL;
this->right = NULL;
bf = 0;
}
};
template <class T>
class AvL
{
AvLNode<T> *head;
public:
// Constructor
AvL();
// Destructor
~AvL();
// Insertion Function
void insert(string val, T k); // inserts the given key value pair into the tree
void Balance(AvLNode<T>* node, T key1);
void delete_node(T k); // deletes the node for the given key
void RightRotate(AvLNode<T>* node);
void LeftRotate(AvLNode<T>* node);
void put(AvLNode<T>* root,string val,T key1);
int nodeHeight(AvLNode<T> *n); // returns height of the subtree from given node
};
Your balance function is wrong. Since you've already inserted your new node into the tree, you don't need to worry about the key any more in Balance() - so the prototype should look like this:
template<class T>
void AvL<T>::Balance(AvLNode<T>* root);
The way you're doing it now seems to be attempting to balance based on the key you just inserted - which isn't necessary! You can balance the tree just based on the balance factors of nodes - here's how.
template<class T>
void AvL<T>::Balance(AvLNode<T>* root) {
if (root->bf > 1) {
if (root->left->bf == -1) LeftRotate(root->left);
RightRotate(root);
} else if (root->bf < -1) {
if (root->right->bf == 1) RightRotate(root->right);
LeftRotate(root);
}
}
You can read more about it here - but you seem to have the idea almost down. The only thing you need to change conceptually is the idea that you're balancing based on the key you just inserted. You're not - you're balancing based on the shape of the tree, which you can get from just the balance factors of each subtree.

Resources