mirror of
https://github.com/TheAlgorithms/C
synced 2024-11-22 13:31:21 +03:00
778f317e82
* Rename redblacktree.c to red_black_tree.c * updating DIRECTORY.md * add renaming avl.c and ascendingpriorityqueue.c * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
798 lines
21 KiB
C
798 lines
21 KiB
C
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
typedef struct node
|
|
{
|
|
int val;
|
|
struct node *par;
|
|
struct node *left;
|
|
struct node *right;
|
|
int color;
|
|
} Node;
|
|
|
|
// Create a new node
|
|
Node *newNode(int val, Node *par)
|
|
{
|
|
Node *create = (Node *)(malloc(sizeof(Node)));
|
|
create->val = val;
|
|
create->par = par;
|
|
create->left = NULL;
|
|
create->right = NULL;
|
|
create->color = 1;
|
|
}
|
|
|
|
// Check if the node is the leaf
|
|
int isLeaf(Node *n)
|
|
{
|
|
if (n->left == NULL && n->right == NULL)
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Left Rotate
|
|
Node *leftRotate(Node *node)
|
|
{
|
|
Node *parent = node->par;
|
|
Node *grandParent = parent->par;
|
|
|
|
parent->right = node->left;
|
|
if (node->left != NULL)
|
|
{
|
|
node->left->par = parent;
|
|
}
|
|
node->par = grandParent;
|
|
parent->par = node;
|
|
node->left = parent;
|
|
if (grandParent != NULL)
|
|
{
|
|
if (grandParent->right == parent)
|
|
{
|
|
grandParent->right = node;
|
|
}
|
|
else
|
|
{
|
|
grandParent->left = node;
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// Right Rotate
|
|
Node *rightRotate(Node *node)
|
|
{
|
|
Node *parent = node->par;
|
|
Node *grandParent = parent->par;
|
|
|
|
parent->left = node->right;
|
|
if (node->right != NULL)
|
|
{
|
|
node->right->par = parent;
|
|
}
|
|
node->par = grandParent;
|
|
parent->par = node;
|
|
node->right = parent;
|
|
if (grandParent != NULL)
|
|
{
|
|
if (grandParent->right == parent)
|
|
{
|
|
grandParent->right = node;
|
|
}
|
|
else
|
|
{
|
|
grandParent->left = node;
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// Check the node after the insertion step
|
|
void checkNode(Node *node)
|
|
{
|
|
// If the node is the root
|
|
if (node == NULL || node->par == NULL)
|
|
{
|
|
return;
|
|
}
|
|
Node *child = node;
|
|
// If it is a black node or its parent is a black node
|
|
if (node->color == 0 || (node->par)->color == 0)
|
|
{
|
|
// Dont Do Anything
|
|
return;
|
|
}
|
|
|
|
// Both parent and child are red
|
|
// Check For Uncle
|
|
Node *parent = node->par;
|
|
Node *grandParent = parent->par;
|
|
|
|
// If grandParent is NULL, then parent is the root.
|
|
// Just make the root black.
|
|
if (grandParent == NULL)
|
|
{
|
|
parent->color = 0;
|
|
return;
|
|
}
|
|
|
|
// If both the children of the grandParent are red
|
|
if (grandParent->right != NULL && (grandParent->right)->color == 1 &&
|
|
grandParent->left != NULL && (grandParent->left)->color == 1)
|
|
{
|
|
// Make the grandParent red and both of its children black
|
|
(grandParent->right)->color = 0;
|
|
(grandParent->left)->color = 0;
|
|
grandParent->color = 1;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
// The only option left is rotation.
|
|
Node *greatGrandParent = grandParent->par;
|
|
// Right Case
|
|
if (grandParent->right == parent)
|
|
{
|
|
// Right Right Case
|
|
if (parent->right == node)
|
|
{
|
|
grandParent->right = parent->left;
|
|
if (parent->left != NULL)
|
|
{
|
|
(parent->left)->par = grandParent;
|
|
}
|
|
parent->left = grandParent;
|
|
grandParent->par = parent;
|
|
|
|
// Attach to existing Tree;
|
|
parent->par = greatGrandParent;
|
|
if (greatGrandParent != NULL)
|
|
{
|
|
if (greatGrandParent->left != NULL &&
|
|
greatGrandParent->left == grandParent)
|
|
{
|
|
greatGrandParent->left = parent;
|
|
}
|
|
else
|
|
{
|
|
greatGrandParent->right = parent;
|
|
}
|
|
}
|
|
|
|
// Change the colors
|
|
parent->color = 0;
|
|
grandParent->color = 1;
|
|
}
|
|
else
|
|
{ // Right Left Case
|
|
// First step -> Parent Child Rotation
|
|
parent->left = child->right;
|
|
if (child->right != NULL)
|
|
{
|
|
(child->right)->par = parent;
|
|
}
|
|
child->right = parent;
|
|
parent->par = child;
|
|
|
|
// Second step -> Child and GrandParent Rotation
|
|
grandParent->right = child->left;
|
|
if (child->left != NULL)
|
|
{
|
|
(child->left)->par = grandParent;
|
|
}
|
|
child->left = grandParent;
|
|
grandParent->par = child;
|
|
|
|
// Attach to the existing tree
|
|
child->par = greatGrandParent;
|
|
if (greatGrandParent != NULL)
|
|
{
|
|
if (greatGrandParent->left != NULL &&
|
|
greatGrandParent->left == grandParent)
|
|
{
|
|
greatGrandParent->left = child;
|
|
}
|
|
else
|
|
{
|
|
greatGrandParent->right = child;
|
|
}
|
|
}
|
|
|
|
// Change The Colors
|
|
child->color = 0;
|
|
grandParent->color = 1;
|
|
}
|
|
}
|
|
else
|
|
{ // Left Case
|
|
// Left Left Case
|
|
if (parent->left == node)
|
|
{
|
|
grandParent->left = parent->right;
|
|
if (parent->right != NULL)
|
|
{
|
|
(parent->right)->par = grandParent;
|
|
}
|
|
parent->right = grandParent;
|
|
grandParent->par = parent;
|
|
|
|
// Attach to existing Tree;
|
|
parent->par = greatGrandParent;
|
|
if (greatGrandParent != NULL)
|
|
{
|
|
if (greatGrandParent->left != NULL &&
|
|
greatGrandParent->left == grandParent)
|
|
{
|
|
greatGrandParent->left = parent;
|
|
}
|
|
else
|
|
{
|
|
greatGrandParent->right = parent;
|
|
}
|
|
}
|
|
|
|
// Change the colors
|
|
parent->color = 0;
|
|
grandParent->color = 1;
|
|
}
|
|
else
|
|
{ // Left Right Case
|
|
|
|
// First step -> Parent Child Rotation
|
|
parent->right = child->left;
|
|
if (child->left != NULL)
|
|
{
|
|
(child->left)->par = parent;
|
|
}
|
|
child->left = parent;
|
|
parent->par = child;
|
|
|
|
// Second step -> Child and GrandParent Rotation
|
|
grandParent->left = child->right;
|
|
if (child->right != NULL)
|
|
{
|
|
(child->right)->par = grandParent;
|
|
}
|
|
child->right = grandParent;
|
|
grandParent->par = child;
|
|
|
|
// Attach to the existing tree
|
|
child->par = greatGrandParent;
|
|
if (greatGrandParent != NULL)
|
|
{
|
|
if (greatGrandParent->left != NULL &&
|
|
greatGrandParent->left == grandParent)
|
|
{
|
|
greatGrandParent->left = child;
|
|
}
|
|
else
|
|
{
|
|
greatGrandParent->right = child;
|
|
}
|
|
}
|
|
|
|
// Change The Colors
|
|
child->color = 0;
|
|
grandParent->color = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// To insert a node in the existing tree
|
|
void insertNode(int val, Node **root)
|
|
{
|
|
Node *buffRoot = *root;
|
|
while (buffRoot)
|
|
{
|
|
if (buffRoot->val > val)
|
|
{
|
|
// Go left
|
|
if (buffRoot->left != NULL)
|
|
{
|
|
buffRoot = buffRoot->left;
|
|
}
|
|
else
|
|
{
|
|
// Insert The Node
|
|
Node *toInsert = newNode(val, buffRoot);
|
|
buffRoot->left = toInsert;
|
|
buffRoot = toInsert;
|
|
|
|
// Check For Double Red Problems
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Go right
|
|
if (buffRoot->right != NULL)
|
|
{
|
|
buffRoot = buffRoot->right;
|
|
}
|
|
else
|
|
{
|
|
// Insert The Node
|
|
Node *toInsert = newNode(val, buffRoot);
|
|
buffRoot->right = toInsert;
|
|
buffRoot = toInsert;
|
|
|
|
// Check For Double Red Problems
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
while (buffRoot != *root)
|
|
{
|
|
checkNode(buffRoot);
|
|
if (buffRoot->par == NULL)
|
|
{
|
|
*root = buffRoot;
|
|
break;
|
|
}
|
|
buffRoot = buffRoot->par;
|
|
if (buffRoot == *root)
|
|
{
|
|
buffRoot->color = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void checkForCase2(Node *toDelete, int delete, int fromDirection, Node **root)
|
|
{
|
|
if (toDelete == (*root))
|
|
{
|
|
(*root)->color = 0;
|
|
return;
|
|
}
|
|
|
|
if (!delete &&toDelete->color == 1)
|
|
{
|
|
if (!fromDirection)
|
|
{
|
|
if (toDelete->right != NULL)
|
|
{
|
|
toDelete->right->color = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (toDelete->left != NULL)
|
|
{
|
|
toDelete->left->color = 1;
|
|
}
|
|
}
|
|
toDelete->color = 0;
|
|
return;
|
|
}
|
|
|
|
// Get the sibling for further inspection
|
|
Node *sibling;
|
|
Node *parent = toDelete->par;
|
|
int locateChild = 0; // 0 if toDeleted is left of its parent else 1
|
|
if (parent->right == toDelete)
|
|
{
|
|
sibling = parent->left;
|
|
locateChild = 1;
|
|
}
|
|
else
|
|
{
|
|
sibling = parent->right;
|
|
}
|
|
|
|
// Case 2.1. i.e. if the any children of the sibling is red
|
|
if ((sibling->right != NULL && sibling->right->color == 1) ||
|
|
(sibling->left != NULL && sibling->left->color == 1))
|
|
{
|
|
if (sibling->right != NULL && sibling->right->color == 1)
|
|
{
|
|
// Sibling is left and child is right. i.e. LEFT RIGHT ROTATION
|
|
if (locateChild == 1)
|
|
{
|
|
int parColor = parent->color;
|
|
|
|
// Step 1: Left rotate sibling
|
|
sibling = leftRotate(sibling->right);
|
|
|
|
// Step 2: Right rotate updated sibling
|
|
parent = rightRotate(sibling);
|
|
|
|
// Check if the root is rotated
|
|
if (parent->par == NULL)
|
|
{
|
|
*root = parent;
|
|
}
|
|
|
|
// Step 3: Update the colors
|
|
parent->color = parColor;
|
|
parent->left->color = 0;
|
|
parent->right->color = 0;
|
|
|
|
// Delete the node (present at parent->right->right)
|
|
if (delete)
|
|
{
|
|
if (toDelete->left != NULL)
|
|
{
|
|
toDelete->left->par = parent->right;
|
|
}
|
|
parent->right->right = toDelete->left;
|
|
free(toDelete);
|
|
}
|
|
}
|
|
else
|
|
{ // Sibling is right and child is also right. i.e. LEFT LEFT
|
|
// ROTATION
|
|
|
|
int parColor = parent->color;
|
|
|
|
// Left Rotate the sibling
|
|
parent = leftRotate(sibling);
|
|
|
|
// Check if the root is rotated
|
|
if (parent->par == NULL)
|
|
{
|
|
*root = parent;
|
|
}
|
|
|
|
// Update Colors
|
|
parent->color = parColor;
|
|
parent->left->color = 0;
|
|
parent->right->color = 0;
|
|
|
|
// Delete the node (present at parent->left->left)
|
|
if (delete)
|
|
{
|
|
if (toDelete->right != NULL)
|
|
{
|
|
toDelete->right->par = parent->left;
|
|
}
|
|
parent->left->left = toDelete->left;
|
|
free(toDelete);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Sibling is right and child is left. i.e. RIGHT LEFT ROTATION
|
|
if (locateChild == 0)
|
|
{
|
|
int parColor = parent->color;
|
|
|
|
// Step 1: Right rotate sibling
|
|
sibling = rightRotate(sibling->left);
|
|
|
|
// printf("%d - reached\n", sibling->val);
|
|
// return;
|
|
|
|
// Step 2: Left rotate updated sibling
|
|
parent = leftRotate(sibling);
|
|
|
|
// Check if the root is rotated
|
|
if (parent->par == NULL)
|
|
{
|
|
*root = parent;
|
|
}
|
|
|
|
// Step 3: Update the colors
|
|
parent->color = parColor;
|
|
parent->left->color = 0;
|
|
parent->right->color = 0;
|
|
|
|
// Delete the node (present at parent->left->left)
|
|
if (delete)
|
|
{
|
|
if (toDelete->right != NULL)
|
|
{
|
|
toDelete->right->par = parent->left;
|
|
}
|
|
parent->left->left = toDelete->right;
|
|
free(toDelete);
|
|
}
|
|
}
|
|
else
|
|
{ // Sibling is left and child is also left. i.e. RIGHT RIGHT
|
|
// ROTATION
|
|
|
|
int parColor = parent->color;
|
|
|
|
// Right Rotate the sibling
|
|
parent = rightRotate(sibling);
|
|
|
|
// Check if the root is rotated
|
|
if (parent->par == NULL)
|
|
{
|
|
*root = parent;
|
|
}
|
|
|
|
// Update Colors
|
|
parent->color = parColor;
|
|
parent->left->color = 0;
|
|
parent->right->color = 0;
|
|
|
|
// Delete the node (present at parent->right->right)
|
|
if (delete)
|
|
{
|
|
if (toDelete->left != NULL)
|
|
{
|
|
toDelete->left->par = parent->right;
|
|
}
|
|
parent->right->right = toDelete->left;
|
|
free(toDelete);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (sibling->color == 0)
|
|
{ // Make the sibling red and recur for its parent
|
|
|
|
// Recolor the sibling
|
|
sibling->color = 1;
|
|
|
|
// Delete if necessary
|
|
if (delete)
|
|
{
|
|
if (locateChild)
|
|
{
|
|
toDelete->par->right = toDelete->left;
|
|
if (toDelete->left != NULL)
|
|
{
|
|
toDelete->left->par = toDelete->par;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
toDelete->par->left = toDelete->right;
|
|
if (toDelete->right != NULL)
|
|
{
|
|
toDelete->right->par = toDelete->par;
|
|
}
|
|
}
|
|
}
|
|
|
|
checkForCase2(parent, 0, locateChild, root);
|
|
}
|
|
else
|
|
{ // Bring the sibling on top and apply 2.1 or 2.2 accordingly
|
|
if (locateChild)
|
|
{ // Right Rotate
|
|
|
|
toDelete->par->right = toDelete->left;
|
|
if (toDelete->left != NULL)
|
|
{
|
|
toDelete->left->par = toDelete->par;
|
|
}
|
|
|
|
parent = rightRotate(sibling);
|
|
|
|
// Check if the root is rotated
|
|
if (parent->par == NULL)
|
|
{
|
|
*root = parent;
|
|
}
|
|
|
|
parent->color = 0;
|
|
parent->right->color = 1;
|
|
checkForCase2(parent->right, 0, 1, root);
|
|
}
|
|
else
|
|
{ // Left Rotate
|
|
|
|
toDelete->par->left = toDelete->right;
|
|
if (toDelete->right != NULL)
|
|
{
|
|
toDelete->right->par = toDelete->par;
|
|
}
|
|
parent = leftRotate(sibling);
|
|
|
|
// Check if the root is rotated
|
|
if (parent->par == NULL)
|
|
{
|
|
*root = parent;
|
|
}
|
|
|
|
printf("\nroot - %d - %d\n", parent->val, parent->left->val);
|
|
|
|
parent->color = 0;
|
|
parent->left->color = 1;
|
|
checkForCase2(parent->left, 0, 0, root);
|
|
}
|
|
}
|
|
}
|
|
|
|
// To delete a node from the tree
|
|
void deleteNode(int val, Node **root)
|
|
{
|
|
Node *buffRoot = *root;
|
|
|
|
// Search for the element in the tree
|
|
while (1)
|
|
{
|
|
if (val == buffRoot->val)
|
|
{
|
|
// Node Found
|
|
break;
|
|
}
|
|
|
|
if (val > buffRoot->val)
|
|
{
|
|
if (buffRoot->right != NULL)
|
|
{
|
|
buffRoot = buffRoot->right;
|
|
}
|
|
else
|
|
{
|
|
printf("Node Not Found!!!");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (buffRoot->left != NULL)
|
|
{
|
|
buffRoot = buffRoot->left;
|
|
}
|
|
else
|
|
{
|
|
printf("Node Not Found!!!");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
Node *toDelete = buffRoot;
|
|
|
|
// Look for the leftmost of right node or right most of left node
|
|
if (toDelete->left != NULL)
|
|
{
|
|
toDelete = toDelete->left;
|
|
while (toDelete->right != NULL)
|
|
{
|
|
toDelete = toDelete->right;
|
|
}
|
|
}
|
|
else if (toDelete->right != NULL)
|
|
{
|
|
toDelete = toDelete->right;
|
|
while (toDelete->left != NULL)
|
|
{
|
|
toDelete = toDelete->left;
|
|
}
|
|
}
|
|
|
|
if (toDelete == *root)
|
|
{
|
|
*root = NULL;
|
|
return;
|
|
}
|
|
|
|
// Swap the values
|
|
buffRoot->val = toDelete->val;
|
|
toDelete->val = val;
|
|
|
|
// Checking for case 1
|
|
if (toDelete->color == 1 ||
|
|
(toDelete->left != NULL && toDelete->left->color == 1) ||
|
|
(toDelete->right != NULL && toDelete->right->color == 1))
|
|
{
|
|
// if it is a leaf
|
|
if (toDelete->left == NULL && toDelete->right == NULL)
|
|
{
|
|
// Delete instantly
|
|
if (toDelete->par->left == toDelete)
|
|
{
|
|
toDelete->par->left = NULL;
|
|
}
|
|
else
|
|
{
|
|
toDelete->par->right = NULL;
|
|
}
|
|
}
|
|
else
|
|
{ // else its child should be red
|
|
|
|
// Check for the exitstence of left node
|
|
if (toDelete->left != NULL)
|
|
{
|
|
// The node should be right to its parent
|
|
toDelete->par->right = toDelete->left;
|
|
toDelete->left->par = toDelete->par;
|
|
toDelete->left->color = 1;
|
|
}
|
|
else
|
|
{ // else the right node should be red
|
|
toDelete->par->left = toDelete->right;
|
|
toDelete->right->par = toDelete->par;
|
|
toDelete->right->color = 1;
|
|
}
|
|
}
|
|
|
|
// Remove the node from memory
|
|
free(toDelete);
|
|
}
|
|
else
|
|
{ // Case 2
|
|
checkForCase2(toDelete, 1, ((toDelete->par->right == toDelete)), root);
|
|
}
|
|
}
|
|
|
|
void printInorder(Node *root)
|
|
{
|
|
if (root != NULL)
|
|
{
|
|
printInorder(root->left);
|
|
printf("%d c-%d ", root->val, root->color);
|
|
printInorder(root->right);
|
|
}
|
|
}
|
|
|
|
void checkBlack(Node *temp, int c)
|
|
{
|
|
if (temp == NULL)
|
|
{
|
|
printf("%d ", c);
|
|
return;
|
|
}
|
|
if (temp->color == 0)
|
|
{
|
|
c++;
|
|
}
|
|
checkBlack(temp->left, c);
|
|
checkBlack(temp->right, c);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
Node *root = NULL;
|
|
int scanValue, choice = 1;
|
|
printf(
|
|
"1 - Input\n2 - Delete\n3 - Inorder Traversel\n0 - Quit\n\nPlease "
|
|
"Enter the Choice - ");
|
|
scanf("%d", &choice);
|
|
while (choice)
|
|
{
|
|
switch (choice)
|
|
{
|
|
case 1:
|
|
printf("\n\nPlease Enter A Value to insert - ");
|
|
scanf("%d", &scanValue);
|
|
if (root == NULL)
|
|
{
|
|
root = newNode(scanValue, NULL);
|
|
root->color = 0;
|
|
}
|
|
else
|
|
{
|
|
insertNode(scanValue, &root);
|
|
}
|
|
printf("\nSuccessfully Inserted %d in the tree\n\n", scanValue);
|
|
break;
|
|
case 2:
|
|
printf("\n\nPlease Enter A Value to Delete - ");
|
|
scanf("%d", &scanValue);
|
|
deleteNode(scanValue, &root);
|
|
printf("\nSuccessfully Inserted %d in the tree\n\n", scanValue);
|
|
break;
|
|
case 3:
|
|
printf("\nInorder Traversel - ");
|
|
printInorder(root);
|
|
printf("\n\n");
|
|
// checkBlack(root,0);
|
|
// printf("\n");
|
|
break;
|
|
default:
|
|
if (root != NULL)
|
|
{
|
|
printf("Root - %d\n", root->val);
|
|
}
|
|
}
|
|
printf(
|
|
"1 - Input\n2 - Delete\n3 - Inorder Traversel\n0 - "
|
|
"Quit\n\nPlease Enter the Choice - ");
|
|
scanf("%d", &choice);
|
|
}
|
|
}
|
|
|
|
// 32 12 50 53 1 2 3 4 5 6 7 8 9
|