How to remove duplicates in a binary search tree? - c

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.

Related

Stuck at deleting node from Binary Search Tree

I have been trying to follow the textbook "Introduction to Algorithms" but I'm stuck at the following step when deleting a node from a BST - when the node to be deleted has both children
My code is below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bst.h"
void error()
{
fprintf(stderr, "%s\n", "Error assigning memory to node");
exit(1);
}
void insert(node **root, int key)
{
node *t1, *t2;
if (*root == NULL) {
printf("Root is null\n");
*root = (node *)malloc(sizeof(node));
if (*root==NULL) {
fprintf(stderr, "%s\n", "Cannot allocate memory for node in Insert");
exit(1);
}
(*root)->key = key;
(*root)->left = (*root)->right = NULL;
}
else {
printf("Root contains data. Inserting new node.\n");
t1 = *root;
while (t1 != NULL) {
t2 = t1;
if (key < t1->key)
t1 = t1->left;
else
t1 = t1->right;
}
if(key < t2->key) {
t2->left = (node *) malloc(sizeof(node));
t2 = t2->left;
if (t2==NULL)
error();
t2 -> key = key;
}
else {
t2->right = (node *) malloc(sizeof(node));
t2 = t2->right;
if (t2==NULL)
error();
t2->key = key;
}
}
}
void inorder(node * root)
{
if (root!=NULL) {
inorder(root->left);
printf("%d ->", root->key);
inorder(root->right);
}
}
node * search(node *root, int key)
{
node * t = root;
while (t!=NULL)
{
if (key == t->key)
return t;
else if (key < t->key)
t = t->left;
else
t = t->right;
}
return NULL;
}
node * getparent(node * root, int key)
{
node * t = root, *parent = NULL;
while (t!=NULL)
{
if (key == t->key)
return parent;
else if (key < t->key)
t = t->left;
else
t = t->right;
parent = t;
}
return NULL;
}
node * delete(node *root, int key)
{
node * todelete = search(root,key), *parent = getparent(root, key), *y;
if (todelete==NULL) {
fprintf(stderr, "%s\n", "Key not found");
exit(2);
}
if (todelete->left == NULL && todelete->right==NULL) { //Deleting node with no children
if (todelete == parent->left)
parent->left = NULL;
else
parent->right = NULL;
free(todelete);
return root;
}
else if (todelete->left && !todelete->right) {
if (todelete == parent->left)
parent->left = todelete->left;
else
parent->right = todelete->right;
free(todelete);
return root;
}
else if (todelete->right & !todelete->left) {
if (todelete == parent->left)
parent->left = todelete->left;
else
parent->right = todelete->right;
free(todelete);
return root;
}
else
{
node * yparent = NULL;
y= todelete->right;
while (y->left!=NULL)
{
y = y->left;
yparent = y;
}
if(yparent != todelete) {
//stuck here
}
}
}
bst.h:
struct treenode
{
int key;
struct treenode *left;
struct treenode *right;
};
typedef struct treenode node;
node * getparent(node * root, int key);
void insert(node **root, int key);
node * search(node *root, int key);
node * delete(node *root, int key);
void inorder(node * root);
Any guidance would be much appreciated. I should be trying to set the y = y->right and then set todelete->right = y correct?
I'm stuck at the following step when deleting a node from a BST - when the node to be deleted has both children
It follows from the properties of a BST that if a node N has two children then every node in the subtree rooted at the left child is less than every node in the subtree rooted at the right child and vise versa. In particular, the largest node in the left subtree, Lmax, is less than all the nodes in the right subtree, and the least node in the right subtree, Rmin, is larger than all the nodes of the left subtree. These are the nodes immediately preceding and following N in an in-order traversal. Both of those descendants are easy to find, and neither has more than one child (else they could neither be max nor min in any subtree).
It follows, then, that if you want to delete node N then you may choose either Lmax or Rmin, delete it from the tree (which is easy because it has at most one child), and replace N with it. Alternatively, delete Lmax or Rmin, and replace the key of node N with the key of that deleted node.
Changed the code to the following and it works (for the delete functions):
static void transplant(node * root, node * u, node * v)
{
node *uparent = getparent(root, u->key);
node * vparent = getparent(root, v->key);
if (uparent == NULL)
root = v;
else if (u == uparent->left)
uparent->left = v;
else uparent->right = v;
if (v!=NULL)
vparent = uparent;
}
node * delete(node *root, int key)
{
node * todelete = search(root,key), *parent = getparent(root, key), *y;
if (todelete==NULL) {
fprintf(stderr, "%s\n", "Key not found");
exit(2);
}
if (todelete->left == NULL && todelete->right==NULL) { //Deleting node with no children
if (todelete == parent->left)
parent->left = NULL;
else
parent->right = NULL;
free(todelete);
return root;
}
else if (todelete->left && !todelete->right) {
if (todelete == parent->left)
parent->left = todelete->left;
else
parent->right = todelete->left;
free(todelete);
return root;
}
else if (todelete->right && !todelete->left) {
if (todelete == parent->left)
parent->left = todelete->right;
else
parent->right = todelete->right;
free(todelete);
return root;
}
else {
y = todelete->right;
while(y->left!=NULL)
{
y = y->left;
}
node *yparent = getparent(root, y->key);
if (yparent != todelete)
{
transplant(root, y, y->right);
y->right = todelete->right;
node * yrightparent = getparent(root, y->right->key);
yrightparent = y;
}
transplant(root, todelete, y);
y->left = todelete->left;
node *yleftparent = getparent(root, y->left->key);
yleftparent = y;
free(todelete);
return root;
}

View AVL tree not giving the correct output

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

How do I find the minimum value in the right subtree of a Binary Search Tree

I am trying to make a deletion function in Binary Search Tree.
I have finished with the deletion function, but I'm having some trouble with the FindMin() function as follows:
BST* delete_node(BST* root, int key)
{
BST* temp;
if (root == NULL)
return root;
else if (key < root->key)
root->left_child = delete_node(root->left_child, key);
else if (key > root->key)
root->right_child = delete_node(root->right_child, key);
else //If the key is found delete it according to the following cases
{
if (root->left_child == NULL && root->right_child == NULL)
{
free(root);
root = NULL;
}
else if (root->left_child == NULL){ //right child exists
temp = root;
root = root->right_child;
free(temp);
}
else if (root->right_child == NULL){ //left child exists
temp = root;
root = root->left_child;
free(temp);
}
else{
temp = FindMin(root->right_child);
root->key = temp->key;
root->right_child = delete_node(root->right_child, temp->key);
}
}
return root; /*Returning the address of node to be reattached to
the parent of the deleted node*/
}
BST* FindMin(BST* root) //This functions finds the minimum key value in the
right subtree
{
BST* temp = NULL;
if (root->left_child != NULL)
{
temp = FindMin(root->left_child);
return temp;
}
else
return root;
}
I'm pretty sure that I'm going to need to fix the FindMin() function to make this work. But I am having trouble with my delete function because every time I delete one node, it gives an error, and I think it's because of FindMin().
This is how I am doing Binary Search Tree.
This is the structure:
struct _Node;
typedef struct _Node* Position;
struct _Node
{
int element;
Position left;
Position right;
};
And this is the function for searching min value:
Position SearchMin(Position P)
{
while(P->left != NULL)
{
P = P->left;
}
return P;
}

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;
}

Nonrecursive/Iterative Binary Search Tree in C (Homework)

How can I create/delete a node in a Binary Search Tree using Iterative Algorithm in C?
Iterative insertion:
struct tree_node *Insert_Element (struct tree_node *root, void *key, void *data) {
struct tree_node *new_node, *node;
node = root;
do {
switch (compare(key, node->key)) {
case -1: {
if (node->left == NULL) {
if ((new_node = create_node(key, data)) == NULL) {
return NULL;
}
node->left = new_node;
return new_node;
}
node = node->left;
} break;
case 1: {
if (node->right == NULL) {
if ((new_node = create_node(key, data)) == NULL) {
return NULL;
}
node->right = new_node;
return new_node;
}
node = node->right;
} break;
default: {
return node;
}
}
} while (node != NULL);
return NULL;
}
Iterative insertion & deletion in BST
struct bst {
int data;
struct bst *left;
struct bst *right;
};
typedef struct bst bst_t;
bst_t *get_new_node(int val)
{
bst_t *node = (bst_t *) malloc(sizeof(bst_t));
node->data = val;
node->left = NULL;
node->right= NULL;
return node;
}
bst_t *insert(bst_t *root, int val)
{
if(!root) return get_new_node(val);
bst_t *prev = NULL, *ptr = root;
char type = ' ';
while(ptr) {
prev = ptr;
if(val < ptr->data) {
ptr = ptr->left;
type = 'l';
} else {
ptr = ptr->right;
type = 'r';
}
}
if(type == 'l')
prev->left = get_new_node(val);
else
prev->right = get_new_node(val);
return root;
}
int find_minimum_value(bst_t *ptr)
{
int min = ptr ? ptr->data : 0;
while(ptr) {
if(ptr->data < min) min = ptr->data;
if(ptr->left) {
ptr = ptr->left;
} else if(ptr->right) {
ptr = ptr->right;
} else ptr = NULL;
}
return min;
}
bst_t *delete(bst_t *root, int val)
{
bst_t *prev = NULL, *ptr = root;
char type = ' ';
while(ptr) {
if(ptr->data == val) {
if(!ptr->left && !ptr->right) { // node to be removed has no children's
if(ptr != root && prev) { // delete leaf node
if(type == 'l')
prev->left = NULL;
else
prev->right = NULL;
} else root = NULL; // deleted node is root
} else if (ptr->left && ptr->right) { // node to be removed has two children's
ptr->data = find_minimum_value(ptr->right); // find minimum value from right subtree
val = ptr->data;
prev = ptr;
ptr = ptr->right; // continue from right subtree delete min node
type = 'r';
continue;
} else { // node to be removed has one children
if(ptr == root) { // root with one child
root = root->left ? root->left : root->right;
} else { // subtree with one child
if(type == 'l')
prev->left = ptr->left ? ptr->left : ptr->right;
else
prev->right = ptr->left ? ptr->left : ptr->right;
}
}
free(ptr);
}
prev = ptr;
if(val < ptr->data) {
ptr = ptr->left;
type = 'l';
} else {
ptr = ptr->right;
type = 'r';
}
}
return root;
}
Nice post. Just a suggestion. I believe, finding a minimum value in a BST doesn't have to traverse the right subtree. Minimum value must be either on the left subtree or node itself(in case if left subtree is null). Function find_minimum_value can be optimized if right subtree traversal is removed.
int find_minimum_value(bst_t *ptr)
{
while(ptr->left) {
ptr = ptr->left;
}
return ptr->data;
}
In C, you can cast the pointers in the tree to intptr_t type and perform bitwise operations to them.
As you traverse down the tree, you can store the 'parent' pointer of a node by xoring it with the pointer you traversed with. You can then traverse back up the tree by xoring the the address of the node you are coming from with the modified pointer.
A worked example of this traditional technique is at http://sites.google.com/site/debforit/efficient-binary-tree-traversal-with-two-pointers
Given the ability to traverse the tree without recursion, you can then create iterative versions of any of the algorithms based on traversing the tree.

Resources