View AVL tree not giving the correct output - c

I am working on a school project that involves implementing an AVL Tree with the functions to insert delete and view. But my program didnt give the correct output when viewing the avl tree with preorder traversal.
The variable for avl tree:
typedef struct Node{
int data;
int height;
struct Node *right;
struct Node *left;
}Node;
Here is my insert function with newnode function call:
Node *newNode(int data){
Node *node = (Node*)malloc(sizeof(Node));
node->data = data;
node->left = NULL;
node->right = NULL;
node->height = 1;
return(node);
}
Node *insertNode(Node *node, int data){
if(node == NULL)
return(newNode(data));
if(data < node->data)
node->left = insertNode(node->left, data);
if(data > node->data)
node->right = insertNode(node->right, data);
if(data == node->data){
printf("No duplicate allowed.");
return node;
}
node->height = getHeight(node);
return(balancing(node, data));
}
Delete function with minvaluenode function call:
Node * minValueNode(Node* node){
Node* current = node;
while (current->left != NULL)
current = current->left;
return current;
}
Node *deleteNode(Node *root, int data){
if(root == NULL){
printf("Value not found.");
return root;
}
else if ( data < root->data )
root->left = deleteNode(root->left, data);
else if( data > root->data )
root->right = deleteNode(root->right, data);
else if(data == root->data){
if( (root->left == NULL) || (root->right == NULL) ){
Node *temp = root->left ? root->left : root->right;
if (temp == NULL){
temp = root;
root = NULL;
}
else
*root = *temp;
free(temp);
}
else{
Node* temp = minValueNode(root->right);
root->data = temp->data;
root->right = deleteNode(root->right,temp->data);
}
}
if(root == NULL)
return root;
root->height = getHeight(root);
return(balancing(root, data));
}
Balancing function with rotate,getbalancefactor, max, and getheight function calls:
int max(int number1, int number2){
return (number1 > number2) ? number1 : number2;
}
int getHeight(Node* n) {
return max(height(n->left), height(n->right)) + 1;
}
int getBalanceFactor(Node *currentNode){
if(currentNode == NULL)
return 0;
return height(currentNode->left) - height(currentNode->right);
}
Node *rightRotate(Node *currentNode){
Node *temp = currentNode->left;
currentNode->left = temp->right;
temp->right = currentNode;
temp->height = getHeight(temp);
currentNode->height = getHeight(currentNode);
return temp;
}
Node *leftRotate(Node *currentNode){
Node *temp = currentNode->right;
currentNode->right = temp->left;
temp->left = currentNode;
temp->height = getHeight(temp);
currentNode->height = getHeight(currentNode);
return temp;
}
Node *balancing(Node *node, int data){
if(getBalanceFactor(node) >= 2 && data < node->left->data)
return rightRotate(node);
if(getBalanceFactor(node) <= -2 && data > node->right->data)
return leftRotate(node);
if(getBalanceFactor(node) >= 2 && data > node->left->data){
node->left = leftRotate(node->left);
return(rightRotate(node));
}
if(getBalanceFactor(node) <= -2 && data < node->right->data){
node->right = rightRotate(node->right);
return(leftRotate(node));
}
return node;
}
My view function:
//print AVL Tree in preorder traversal
void printAVLTree(Node *root){
if(root != NULL)
{
printf("%d ", root->data);
printAVLTree(root->left);
printAVLTree(root->right);
}
}
I made a test with random insert input:
9 5 10 6 0 11 -1 1 2
The output when calling the view function is:
5 1 0 -1 2 9 6 10 11
The correct output should be:
9 1 0 -1 5 2 6 10 11

Your mistake is that you are updating the height values in the wrong order (top to bottom):
temp->height = getHeight(temp);
currentNode->height = getHeight(currentNode);
After rotation, the lower node is currentNode so you have to update it first.
Otherwise, if you update temp before updating currentNode, temp will use the previous value of currentNode height and will have a wrong height

Related

How to remove duplicates in a binary search tree?

I'm trying to write a function that removes redundant items in a binary search tree. I am completely stuck. Can anyone help me? Any help would be appreciated. (C program)
As #Jack Lilhammers pointed out in comments, it would be nice to create new empty tree and insert it nodes from the original tree... You can do it in this way.
Create an empty binary search tree.
Extract the root node of original bst and insert it to T if it doesn't exist in new tree
Delete root node of your original bst
Do step 2-3 recursively until there are no nodes in the original tree
Let's implement needed procedures to create a complete working program. First Include necessary libraries to work
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
Node structure will be
typedef struct node{
int key;
struct node *left, *right, *parent;
}BST;
First we need to implement create_empty_bst procedure
BST create_empty_bst(void){
BST* root = NULL;
return root;
}
To insert extracted root node, we need insert function. Its return value can both be void or BST which completely depends on us. If we would use void return type, then the function needs to take pointer to pointer to the root of the tree (aka. double pointer); otherwise, we can pass pointer to root of the tree, and return root of the tree. you can do either way. I will use the second one
BST*new_Node(int data){
BST* node = (BST*)malloc(sizeof(struct node));
assert(node != NULL); // or you can write if(node == NULL) printf("error"); exit(0);
node->key = data;
node->left = node->right = node->parent = NULL; // node is inserted always at leaf. so pointers are NULL
return node;
}
void insert(BST** root, int x) {
BST* node = new_Node(x);
BST* p = NULL, * y = *root;
while (y != NULL) {
p = y;
if (y->key == x)
return;
if (y->key > node->key)
y = y->left;
else
y = y->right;
}
node->parent = p;
if (p == NULL)
*root = node;
else if (p->key > node->key)
p->left = node;
else
p->right = node;
}
New_Node(x) creates node with appropriate attributes. Only addition made to insert function is:
if(y->key == x)
return;
when y->key == x, we encountered with a duplicate value. We don't go any further and terminate the procedure. By using this if, we prevent duplicate values to be inserted into the new tree.
The most complex and time-consuming part of the program is the DELETE procedure. We need to implement 4 other procedures to make deletion complete. Those 4 procedures are: SEARCH(BST*root, int x), SUCCESSOR(BST* node), find_min(BST* node), and TRANSPLANT(BST* root, BST* u, BST* v). If you have difficulty in understand DELETE, you can look at Binary Search Tree (Chapter 12) in CLRS. I get this DELETE from this book. Those 5 procedures are implemented as follows:
BST* TRANSPLANT(BST* root, BST* u, BST* v) {
if (u->parent == NULL)
root = v;
else if (u->parent->left == u)
u->parent->left = v;
else
u->parent->right = v;
if (v != NULL)
v->parent = u->parent;
return root;
}
BST* find_min(BST* node) {
if (node == NULL)
return node;
while (node->left)
node = node->left;
return node;
}
find_min(node) finds the smallest element on the subtree rooted at node node, if there's any.
BST* SUCCESSOR(BST* node) {
if (node == NULL)
return node;
if (node->right != NULL)
return find_min(node->right);
while (node->parent != NULL && node->parent->right == node)
node = node->parent;
return node->parent;
}
SUCCESSOR(node) finds the next larger element greater than node->key on the subtree rooted at node node, if there's any.
BST* SEARCH(BST* N, int x) {
if (N == NULL || N->key == x)
return N;
else if (N->key > x)
return SEARCH(N->left, x);
else
return SEARCH(N->right, x);
}
BST* DELETE(BST* root, int x) {
BST* node = SEARCH(root, x);
assert(node != NULL);
BST* bosh = root;
if (node->right == NULL) {
root = TRANSPLANT(bosh, node, node->left);
}
else if (node->left == NULL) {
root = TRANSPLANT(bosh, node, node->right);
}
else {
BST* temp = SUCCESSOR(node);
if (node->right != temp) {
root = TRANSPLANT(root, temp, temp->right);
temp->right = node->right;
temp->right->parent = temp;
}
root = TRANSPLANT(root, node, temp);
temp->left = node->left;
temp->left->parent = temp;
}
return root;
}
We have all to implement DELETE_DUPLICATES(BST* new_tree, BST* original) procedure.
BST* DELETE_DUPLICATES(BST* new_tree, BST* original) {
while (original) {
insert(&new_tree, original->key);
original = DELETE(original, original->key);
}
return new_tree;
}
We are done. To test, I'll write whole program so you can see all procedures easily.
Below is the program as whole, rather than as separate procedures implemented above.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct node {
int key;
struct node* left, * right, * parent;
}BST;
void preorder(BST*);
BST* DELETE_DUPLICATES(BST*, BST*);
void display_tree(BST*);
BST* create_empty_bst(void);
BST* new_Node(int);
void insert(BST**, int);
BST* insertSimple(BST*, int);
BST* TRANSPLANT(BST*, BST*, BST*);
BST* SUCCESSOR(BST*);
BST* find_min(BST* );
BST* SEARCH(BST*, int);
BST* DELETE(BST*, int);
BST* create_empty_bst(void) {
BST* root = NULL;
return root;
}
BST* new_Node(int data) {
BST* node = (BST*)malloc(sizeof(struct node));
assert(node != NULL); // or you can write if(node == NULL) printf("error"); exit(0);
node->key = data;
node->left = node->right = node->parent = NULL; // node is inserted always at leaf. so pointers are NULL
return node;
}
void insert(BST** root, int x) {
BST* node = new_Node(x);
BST* p = NULL, * y = *root;
while (y != NULL) {
p = y;
if (y->key == x)
return;
if (y->key > node->key)
y = y->left;
else
y = y->right;
}
node->parent = p;
if (p == NULL)
*root = node;
else if (p->key > node->key)
p->left = node;
else
p->right = node;
}
BST* insertSimple(BST* root, int x) {
BST* node = new_Node(x);
BST* p = NULL, * y = root;
while (y != NULL) {
p = y;
if (y->key > node->key)
y = y->left;
else
y = y->right;
}
node->parent = p;
if (p == NULL)
root = node;
else if (p->key > node->key)
p->left = node;
else
p->right = node;
return root;
}
BST* TRANSPLANT(BST* root, BST* u, BST* v) {
if (u->parent == NULL)
root = v;
else if (u->parent->left == u)
u->parent->left = v;
else
u->parent->right = v;
if (v != NULL)
v->parent = u->parent;
return root;
}
BST* find_min(BST* node) {
if (node == NULL)
return node;
while (node->left)
node = node->left;
return node;
}
BST* SUCCESSOR(BST* node) {
if (node == NULL)
return node;
if (node->right != NULL)
return find_min(node->right);
while (node->parent != NULL && node->parent->right == node)
node = node->parent;
return node->parent;
}
BST* SEARCH(BST* N, int x) {
if (N == NULL || N->key == x)
return N;
else if (N->key > x)
return SEARCH(N->left, x);
else
return SEARCH(N->right, x);
}
BST* DELETE(BST* root, int x) {
BST* node = SEARCH(root, x);
assert(node != NULL);
BST* bosh = root;
if (node->right == NULL) {
root = TRANSPLANT(bosh, node, node->left);
}
else if (node->left == NULL) {
root = TRANSPLANT(bosh, node, node->right);
}
else {
BST* temp = SUCCESSOR(node);
if (node->right != temp) {
root = TRANSPLANT(root, temp, temp->right);
temp->right = node->right;
temp->right->parent = temp;
}
root = TRANSPLANT(root, node, temp);
temp->left = node->left;
temp->left->parent = temp;
}
return root;
}
void preorder(BST* root) {
if (root) {
printf("%d ", root->key);
preorder(root->left);
preorder(root->right);
}
}
void display_tree(BST* root) {
preorder(root);
printf("\n");
}
BST* DELETE_DUPLICATES(BST* new_tree, BST* original) {
while (original) {
insert(&new_tree, original->key);
original = DELETE(original, original->key);
}
return new_tree;
}
int main(void) {
BST* new_tree = NULL, * original = NUL;
original = insertSimple(original, 20); original = insertSimple(original, 20);
original = insertSimple(original, 12);
original = insertSimple(original, 30);
original = insertSimple(original, 18);
original = insertSimple(original, 12);
original = insertSimple(original, 30);
original = insertSimple(original, 11);
display_tree(original);
display_tree(new_tree);
new_tree = DELETE_DUPLICATES(new_tree, original);
display_tree(new_tree);
return 0;
}
NOTES: insertSimple function inserts elements into the original tree. We can't use insert procedure because it doesn't insert duplicate elements. insertSimple procedure is written for that purpose. preorder procedure prints the elements in the preorder form. (If have difficulty, look at preorder traversal). That's it, I wish you success in your work.

BST - Deleting a Node

so I'm trying to solve a problem from log2base2.com involving deleting a node from BST. It works except when trying to delete a node with two children. I know I could simply replace the numbers and then delete the duplicate at the end, but what if my struct has more data than just key? So what am I doing wrong please?
#include<stdio.h>
#include<stdlib.h>
struct node
{
int key;
struct node *left;
struct node *right;
};
int getRightMin(struct node *root)
{
//Write your code here
struct node *temp = root;
while(temp->left!=NULL)
{
temp=temp->left;
}
return temp;
}
struct node *removeNode(struct node *root, int key)
{
//Write your code here
if(root == NULL){return NULL;}
if(key<root->key){root->left = removeNode(root->left, key);}
else if(key>root->key){root->right = removeNode(root->right,key);}
else
{
if(root->left==NULL && root->right==NULL)
{
free(root);
return NULL;
}
else if(root->left)
{
struct node *temp = root->left;
free(root);
return temp;
}
else if(root->right)
{
struct node *temp = root->right;
free(root);
return temp;
}
else
{
struct node *temp = getRightMin(root->right);
temp->left = root->left;
temp->right = root->right;
root = temp;
root->right = removeNode(root->right, temp->key);
}
}
return root;
}
//Don't change the below code
struct node *getNewNode(int val)
{
struct node *newNode = malloc(sizeof(struct node));
newNode->key = val;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
struct node *insert(struct node *root, int val)
{
if(root == NULL)
return getNewNode(val);
if(root->key < val)
root->right = insert(root->right,val);
else if(root->key > val)
root->left = insert(root->left,val);
return root;
}
void inorder(struct node *root)
{
if(root == NULL)
return;
inorder(root->left);
printf("%d ",root->key);
inorder(root->right);
}
int main()
{
struct node *root = NULL;
root = insert(root,100);
root = insert(root,50);
root = insert(root,200);
root = insert(root,150);
root = insert(root,300);
int key;
scanf("%d",&key);
root = removeNode(root,key);
inorder(root);
return 0;
}
TEST CASE 1:
INPUT: 200
EXPECTED OUTPUT: 50 100 150 300
ACTUAL OUTPUT: 50 100 150
TEST CASE 2:
INPUT: 100
EXPECTED OUTPUT: 50 150 200 300
ACTUAL OUTPUT: 50
You have to reorder conditional in removeNode() to:
if(root->left==NULL && root->right==NULL)
{
free(root);
return NULL;
}
else if (root->left && root->right)
{
struct node *temp = getRightMin(root->right);
temp->left = root->left;
temp->right = root->right;
root = temp;
root->right = removeNode(root->right, temp->key);
}
else if(root->left)
{
struct node *temp = root->left;
free(root);
return temp;
}
else // root->right != NULL
{
struct node *temp = root->right;
free(root);
return temp;
}
It looks that (root->left && root->right) case was caught by (root->left) and
reference to root->right was lost.

Deletion of node in Binary Search Tree is throwing error

Experts, this is my code of creation and deletion of nodes in Binary Search Tree. It's working fine for insertion, but throwing segmentation fault (core dumped) when trying to delete a node (on invoking deleteNode( ) function). I don't understand what's actually the problem. Please help! Thank you in advance!
#include <stdio.h>
#include <stdlib.h>
int size = 0;
typedef struct mylist{
int data;
struct mylist *left;
struct mylist *right;
}node;
node *root;
void create_root(node *root){
root = NULL;
}
//Inserting nodes
node* insert(node *root, int val){
node *ptr, *parentptr, *nodeptr;
ptr = (node*)malloc(sizeof(node));
ptr -> data = val;
ptr -> left = NULL;
ptr -> right = NULL;
if(root == NULL)
root = ptr;
else{
parentptr = NULL;
nodeptr = root;
while(nodeptr != NULL){
parentptr=nodeptr;
if(val < nodeptr -> data)
nodeptr = nodeptr -> left;
else
nodeptr = nodeptr -> right;
}
if(val < parentptr -> data)
parentptr -> left = ptr;
else
parentptr -> right = ptr;
}
return root;
}
node* minValueNode(node* root)
{
node* cur = root;
while (cur->left != NULL)
cur = cur->left;
return cur;
}
node* deleteNode(node* root, int key)
{
if (root == NULL){
printf("\nValue not found\n");
}
if (key < root-> data)
root->left = deleteNode(root->left, key);
else if (key > root-> data)
root->right = deleteNode(root->right, key);
else
{
if (root->left == NULL)
{
node *temp = root->right;
free(root);
return temp;
}
else if (root->right == NULL)
{
node *temp = root->left;
free(root);
return temp;
}
node* temp = minValueNode(root->right); //Inorder successor
root->data = temp->data;
root->right = deleteNode(root->right, temp->data);
}
return root;
}
void main(){
int option, val;
node *ptr;
int flag = 1;
create_root(root);
while(flag != 2){
printf("\nChoose-\n1-Insert\n2-Delete\n3-Exit\n");
scanf("%d", &option);
switch(option){
case 1:{
printf("\nEnter the value of new node\n");
size++;
scanf("%d", &val);
root = insert(root, val);
break;
}
case 2:{
int k;
printf("Enter the value to delete");
scanf("%d",&k);
root=deleteNode(root, k);
size--;
break;
}
case 3:
flag=2;
break;
default:
printf("\nWrong entry\n");
}
}
}
You must either return NULL in the first if() in deleteNode(), or you must put an else before the second if()
node* deleteNode(node* root, int key)
{
if (root == NULL){
printf("\nValue not found\n");
return NULL; // <== This was missing.
}
...
}
or alternatively (perhaps intended?):
node* deleteNode(node* root, int key)
{
if (root == NULL){
printf("\nValue not found\n");
}
else if(key < root->data)
...
}
At the moment this falls through to the next if(key < root->data) even when root is null, which causes the segfault.
Also: Use nullptr if you can use C++11.

Deleting a node with 2 children from a binary search tree

I am trying to delete a node having 2 chidren in a binary search tree. However i am facing little problem here. While deleting node(node with data=30) with children (left->data=20,right->data=40), I am replacing the node with its inorder successor (which is node with data=40) and then deleting the inorder successor. After deletion the node's data is successfully replaced (new value being 40) but the inorder successor is not being deleted/freed properly.
Expected Output [inorder traversal]: 20->40->50->60->70->80->
Output[inorder traversal]: 20->40->0->50->60->70->80->
After 40, why is the value 0 appearing?
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *left;
struct Node *right;
};
struct Node* temp = NULL,*temp1 = NULL;
struct Node *newNode(int data)
{
struct Node *node = (struct Node*)malloc(sizeof(struct Node));
node->data = data;
node->left = node->right = NULL;
return node;
}
struct Node* insert(struct Node* root,int data)
{
if(root == NULL)
{
return newNode(data);
}
if(data < root->data)
root->left = insert(root->left,data);
else
root->right = insert(root->right,data);
}
void inorder(struct Node* root)
{
if(root!=NULL)
{
inorder(root->left);
printf("%d->",root->data);
inorder(root->right);
}
else
{
return;
}
}
/*to find the inorder successor*/
struct Node *minVal(struct Node *root)
{
while(root->left !=NULL)
{
temp = root;
root = root->left;
}
return root;
}
void deleteNode(struct Node *root,int data)
{
if(data < root->data)
{
temp = root;
deleteNode(root->left,data);
}
else if(data > root->data)
{
temp = root;
deleteNode(root->right,data);
}
else if(data == root->data)
{ /*deleting leaf nodes*/
if(root->left == NULL && root->right == NULL)
{
if(temp->left == root)
temp->left = NULL;
else
if(temp->right == root)
temp->right = NULL;
free(root);
root = NULL;
return;
}
/*deleting nodes having single child*/
else if(root->left !=NULL && root->right == NULL)
{
temp1 = root->left;
temp->left = temp1;
free(root);
root = NULL;
}
else if(root->left ==NULL && root->right != NULL)
{
temp1 = root->right;
temp->right = temp1;
free(root);
root = NULL;
}
/*deleting nodes having 2 children*/
else if(root->left !=NULL && root->right !=NULL)
{
struct Node *temp2 = minVal(root->right);
root->data = temp2->data;
deleteNode(root->right,temp2->data);
}
}
}
int main()
{
struct Node *root = NULL;
printf("\n\n");
root = insert(root, 50);
insert(root, 30);
insert(root, 20);
insert(root, 40);
insert(root, 70);
insert(root, 60);
insert(root, 80);
inorder(root);
//deleteNode(root,40);
deleteNode(root,30);
printf("\n\n");
inorder(root);
printf("\n\n");
}

Delete function in Binary Tree in C

I'm writing the basic functions for binary tree and everything seems to compile and run, but when i try to use my delete function it doesn't do anything.
After executing i get the same sequence of numbers, so i'm trying to figure out what's wrong with the Delete function, is it logically correct?
#include <stdio.h>
#include <stdlib.h>
typedef struct treeNode
{
int data;
struct treeNode *left;
struct treeNode *right;
}treeNode;
treeNode *Insert(treeNode *node, int data)
{
if(node == NULL)
{
treeNode *temp;
temp = malloc(sizeof(treeNode));
temp->data = data;
temp->left = temp->right = NULL;
return temp;
}
if(data > (node->data))
{
node->right = Insert(node->right, data);
}
else if(data < (node->data))
{
node->left = Insert(node->left, data);
}
return node;
}
treeNode *Delete(treeNode *node, int data)
{
if(node == NULL)
{
printf("element not found\n");
}
else if(data < node->data)
{
node->left = Delete(node->left, data);
}
else if(data > node->data)
{
node->right = Delete(node->right, data);
}
return node;
}
treeNode *Find(treeNode *node, int data)
{
if(node == NULL)
{
return NULL;
}
if(data > node->data)
{
return Find(node->right, data);
}
else if(data < node->data)
{
return Find(node->left, data);
}
else
{
return node;
}
}
void Print(treeNode *node)
{
if(node == NULL)
{
return;
}
Print(node->left);
printf("%d", node->data);
Print(node->right);
}
int main()
{
treeNode *root = NULL;
root = Insert(root, 5);
root = Insert(root, 8);
root = Insert(root, 6);
root = Insert(root, 4);
root = Insert(root, 3);
root = Insert(root, 9);
root = Insert(root, 10);
root = Insert(root, 19);
Print(root);
printf("\n");
root = Delete(root, 5);
root = Delete(root, 8);
Print(root);
printf("\n");
treeNode *temp;
temp = Find(root, 8);
if(temp == NULL)
{
printf("Element 8 not found\n");
}
else
{
printf("Element 8 found\n");
}
temp = Find(root, 5);
if(temp == NULL)
{
printf("element 5 not found\n");
}
else
{
printf("element 5 found\n");
}
}
Basically i was only replacing the node with itself, but this can be solved by replacing the deleted node with the minimum element in the right subtree or the maximum element in the left subtree.
The function that works:
treeNode * Delete(treeNode *node, int data)
{
treeNode *temp;
if(node==NULL)
{
printf("Element Not Found");
}
else if(data < node->data)
{
node->left = Delete(node->left, data);
}
else if(data > node->data)
{
node->right = Delete(node->right, data);
}
else
{
/* Now We can delete this node and replace with either minimum element
in the right sub tree or maximum element in the left subtree*/
if(node->right && node->left)
{
/* Here we will replace with minimum element in the right sub tree */
temp = FindMin(node->right);
node -> data = temp->data;
/* As we replaced it with some other node, we have to delete that node */
node -> right = Delete(node->right,temp->data);
}
else
{
/* If there is only one or zero children then we can directly
remove it from the tree and connect its parent to its child */
temp = node;
if(node->left == NULL)
node = node->right;
else if(node->right == NULL)
node = node->left;
free(temp); /* temp is longer required */
}
}
return node;
}

Resources