Implement red-black tree algorithm
All checks were successful
Builds / ExectOS (amd64, debug) (push) Successful in 40s
Builds / ExectOS (amd64, release) (push) Successful in 49s
Builds / ExectOS (i686, debug) (push) Successful in 38s
Builds / ExectOS (i686, release) (push) Successful in 46s

This commit is contained in:
2026-05-21 14:56:44 +02:00
parent 72a03f641d
commit 9002ac8b5c
6 changed files with 849 additions and 38 deletions

View File

@@ -14,51 +14,55 @@
/* UUID string lengths */ /* UUID string lengths */
#define GUID_STRING_LENGTH 38 #define GUID_STRING_LENGTH 38
#define PARTUUID_STRING_LENGTH 13 #define PARTUUID_STRING_LENGTH 13
/* Maximum double/integer value string length */ /* Maximum double/integer value string length */
#define MAX_DOUBLE_STRING_SIZE 15 #define MAX_DOUBLE_STRING_SIZE 15
#define MAX_INTEGER_STRING_SIZE 25 #define MAX_INTEGER_STRING_SIZE 25
/* Floating point definitions */ /* Floating point definitions */
#define DOUBLE_EXPONENT_MASK 0x7FF0000000000000ULL #define DOUBLE_EXPONENT_MASK 0x7FF0000000000000ULL
#define DOUBLE_EXPONENT_SHIFT 0x34 #define DOUBLE_EXPONENT_SHIFT 0x34
#define DOUBLE_EXPONENT_BIAS 0x3FF #define DOUBLE_EXPONENT_BIAS 0x3FF
#define DOUBLE_HIGH_VALUE_MASK 0x000FFFFF #define DOUBLE_HIGH_VALUE_MASK 0x000FFFFF
#define DOUBLE_HIGH_VALUE_SHIFT 0x20 #define DOUBLE_HIGH_VALUE_SHIFT 0x20
#define DOUBLE_PRECISION 6 #define DOUBLE_PRECISION 6
#define DOUBLE_HEX_PRECISION 13 #define DOUBLE_HEX_PRECISION 13
#define DOUBLE_SCIENTIFIC_PRECISION -4 #define DOUBLE_SCIENTIFIC_PRECISION -4
#define DOUBLE_SIGN_BIT 0x8000000000000000ULL #define DOUBLE_SIGN_BIT 0x8000000000000000ULL
/* Print flag definitions */ /* Print flag definitions */
#define PFL_ALWAYS_PRINT_SIGN 0x00000001 #define PFL_ALWAYS_PRINT_SIGN 0x00000001
#define PFL_SPACE_FOR_PLUS 0x00000002 #define PFL_SPACE_FOR_PLUS 0x00000002
#define PFL_LEFT_JUSTIFIED 0x00000004 #define PFL_LEFT_JUSTIFIED 0x00000004
#define PFL_LEADING_ZEROES 0x00000008 #define PFL_LEADING_ZEROES 0x00000008
#define PFL_LONG_INTEGER 0x00000010 #define PFL_LONG_INTEGER 0x00000010
#define PFL_LONG_DOUBLE 0x00000020 #define PFL_LONG_DOUBLE 0x00000020
#define PFL_WIDE_CHARACTER 0x00000040 #define PFL_WIDE_CHARACTER 0x00000040
#define PFL_SHORT_VALUE 0x00000080 #define PFL_SHORT_VALUE 0x00000080
#define PFL_UNSIGNED 0x00000100 #define PFL_UNSIGNED 0x00000100
#define PFL_UPPERCASE 0x00000200 #define PFL_UPPERCASE 0x00000200
#define PFL_PRINT_RADIX 0x00000400 #define PFL_PRINT_RADIX 0x00000400
#define PFL_FLOAT_FORMAT 0x00000800 #define PFL_FLOAT_FORMAT 0x00000800
#define PFL_SCI_FORMAT 0x00001000 #define PFL_SCI_FORMAT 0x00001000
#define PFL_DIGIT_PRECISION 0x00002000 #define PFL_DIGIT_PRECISION 0x00002000
#define PFL_THOUSANDS_GROUPING 0x00004000 #define PFL_THOUSANDS_GROUPING 0x00004000
/* Red-black tree definitions */
#define RTL_BALANCED_NODE_RESERVED_PARENT_MASK 3
#define RTL_BALANCED_NODE_COLOR_MASK 1
/* Cryptographic related definitions */ /* Cryptographic related definitions */
#define SHA1_BLOCK_SIZE 64 #define SHA1_BLOCK_SIZE 64
#define SHA1_DIGEST_SIZE 20 #define SHA1_DIGEST_SIZE 20
/* Time related definitions */ /* Time related definitions */
#define TIME_SECONDS_PER_MINUTE 60 #define TIME_SECONDS_PER_MINUTE 60
#define TIME_SECONDS_PER_HOUR 3600 #define TIME_SECONDS_PER_HOUR 3600
#define TIME_SECONDS_PER_DAY 86400 #define TIME_SECONDS_PER_DAY 86400
#define TIME_TICKS_PER_SECOND 10000000 #define TIME_TICKS_PER_SECOND 10000000
#define TIME_TICKS_PER_MILLISECOND 10000 #define TIME_TICKS_PER_MILLISECOND 10000
/* C/C++ specific code */ /* C/C++ specific code */
@@ -68,6 +72,13 @@
typedef XTSTATUS (*PWRITE_CHARACTER)(IN CHAR Character); typedef XTSTATUS (*PWRITE_CHARACTER)(IN CHAR Character);
typedef XTSTATUS (*PWRITE_WIDE_CHARACTER)(IN WCHAR Character); typedef XTSTATUS (*PWRITE_WIDE_CHARACTER)(IN WCHAR Character);
/* Red-black tree node color enumeration list */
typedef enum _RTL_BALANCED_NODE_COLOR
{
NodeBlack,
NodeRed
} RTL_BALANCED_NODE_COLOR, *PRTL_BALANCED_NODE_COLOR;
/* Variable types enumeration list */ /* Variable types enumeration list */
typedef enum _RTL_VARIABLE_TYPE typedef enum _RTL_VARIABLE_TYPE
{ {
@@ -84,6 +95,26 @@ typedef enum _RTL_VARIABLE_TYPE
TypeWideString TypeWideString
} RTL_VARIABLE_TYPE, *PRTL_VARIABLE_TYPE; } RTL_VARIABLE_TYPE, *PRTL_VARIABLE_TYPE;
/* Runtime Library red-black tree balanced node structure definition */
typedef struct _RTL_BALANCED_NODE
{
union
{
PRTL_BALANCED_NODE Children[2];
struct
{
PRTL_BALANCED_NODE Left;
PRTL_BALANCED_NODE Right;
};
};
union
{
UCHAR Red:1;
UCHAR Balance:2;
ULONG_PTR ParentValue;
};
} RTL_BALANCED_NODE, *PRTL_BALANCED_NODE;
/* Bit Map structure definition */ /* Bit Map structure definition */
typedef struct _RTL_BITMAP typedef struct _RTL_BITMAP
{ {
@@ -110,12 +141,19 @@ typedef struct _RTL_PRINT_FORMAT_PROPERTIES
LONG Flags; LONG Flags;
} RTL_PRINT_FORMAT_PROPERTIES, *PRTL_PRINT_FORMAT_PROPERTIES; } RTL_PRINT_FORMAT_PROPERTIES, *PRTL_PRINT_FORMAT_PROPERTIES;
/* Runtime Library red-black tree structure definition */
typedef struct _RTL_RB_TREE
{
PRTL_BALANCED_NODE Root;
PRTL_BALANCED_NODE Min;
} RTL_RB_TREE, *PRTL_RB_TREE;
/* Runtime Library SHA-1 context structure definition */ /* Runtime Library SHA-1 context structure definition */
typedef struct _RTL_SHA1_CONTEXT typedef struct _RTL_SHA1_CONTEXT
{ {
ULONG State[5]; ULONG State[5];
ULONG Count[2]; ULONG Count[2];
UCHAR Buffer[SHA1_BLOCK_SIZE]; UCHAR Buffer[SHA1_BLOCK_SIZE];
} RTL_SHA1_CONTEXT, *PRTL_SHA1_CONTEXT; } RTL_SHA1_CONTEXT, *PRTL_SHA1_CONTEXT;
/* Runtime time fields structure definition */ /* Runtime time fields structure definition */

View File

@@ -57,6 +57,7 @@ typedef enum _MMPFN_CACHE_ATTRIBUTE MMPFN_CACHE_ATTRIBUTE, *PMMPFN_CACHE_ATTRIBU
typedef enum _MMPOOL_TYPE MMPOOL_TYPE, *PMMPOOL_TYPE; typedef enum _MMPOOL_TYPE MMPOOL_TYPE, *PMMPOOL_TYPE;
typedef enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE, *PMMSYSTEM_PTE_POOL_TYPE; typedef enum _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE, *PMMSYSTEM_PTE_POOL_TYPE;
typedef enum _MODE MODE, *PMODE; typedef enum _MODE MODE, *PMODE;
typedef enum _RTL_BALANCED_NODE_COLOR RTL_BALANCED_NODE_COLOR, *PRTL_BALANCED_NODE_COLOR;
typedef enum _RTL_VARIABLE_TYPE RTL_VARIABLE_TYPE, *PRTL_VARIABLE_TYPE; typedef enum _RTL_VARIABLE_TYPE RTL_VARIABLE_TYPE, *PRTL_VARIABLE_TYPE;
typedef enum _SYSTEM_FIRMWARE_TYPE SYSTEM_FIRMWARE_TYPE, *PSYSTEM_FIRMWARE_TYPE; typedef enum _SYSTEM_FIRMWARE_TYPE SYSTEM_FIRMWARE_TYPE, *PSYSTEM_FIRMWARE_TYPE;
typedef enum _SYSTEM_RESOURCE_TYPE SYSTEM_RESOURCE_TYPE, *PSYSTEM_RESOURCE_TYPE; typedef enum _SYSTEM_RESOURCE_TYPE SYSTEM_RESOURCE_TYPE, *PSYSTEM_RESOURCE_TYPE;
@@ -327,9 +328,11 @@ typedef struct _POOL_TRACKING_BIG_ALLOCATIONS POOL_TRACKING_BIG_ALLOCATIONS, *PP
typedef struct _POOL_TRACKING_TABLE POOL_TRACKING_TABLE, *PPOOL_TRACKING_TABLE; typedef struct _POOL_TRACKING_TABLE POOL_TRACKING_TABLE, *PPOOL_TRACKING_TABLE;
typedef struct _PROCESSOR_IDENTITY PROCESSOR_IDENTITY, *PPROCESSOR_IDENTITY; typedef struct _PROCESSOR_IDENTITY PROCESSOR_IDENTITY, *PPROCESSOR_IDENTITY;
typedef struct _PROCESSOR_POWER_STATE PROCESSOR_POWER_STATE, *PPROCESSOR_POWER_STATE; typedef struct _PROCESSOR_POWER_STATE PROCESSOR_POWER_STATE, *PPROCESSOR_POWER_STATE;
typedef struct _RTL_BALANCED_NODE RTL_BALANCED_NODE, *PRTL_BALANCED_NODE;
typedef struct _RTL_BITMAP RTL_BITMAP, *PRTL_BITMAP; typedef struct _RTL_BITMAP RTL_BITMAP, *PRTL_BITMAP;
typedef struct _RTL_PRINT_CONTEXT RTL_PRINT_CONTEXT, *PRTL_PRINT_CONTEXT; typedef struct _RTL_PRINT_CONTEXT RTL_PRINT_CONTEXT, *PRTL_PRINT_CONTEXT;
typedef struct _RTL_PRINT_FORMAT_PROPERTIES RTL_PRINT_FORMAT_PROPERTIES, *PRTL_PRINT_FORMAT_PROPERTIES; typedef struct _RTL_PRINT_FORMAT_PROPERTIES RTL_PRINT_FORMAT_PROPERTIES, *PRTL_PRINT_FORMAT_PROPERTIES;
typedef struct _RTL_RB_TREE RTL_RB_TREE, *PRTL_RB_TREE;
typedef struct _SINGLE_LIST_ENTRY SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; typedef struct _SINGLE_LIST_ENTRY SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY;
typedef struct _SMBIOS_TABLE_HEADER SMBIOS_TABLE_HEADER, *PSMBIOS_TABLE_HEADER; typedef struct _SMBIOS_TABLE_HEADER SMBIOS_TABLE_HEADER, *PSMBIOS_TABLE_HEADER;
typedef struct _SMBIOS3_TABLE_HEADER SMBIOS3_TABLE_HEADER, *PSMBIOS3_TABLE_HEADER; typedef struct _SMBIOS3_TABLE_HEADER SMBIOS3_TABLE_HEADER, *PSMBIOS3_TABLE_HEADER;

View File

@@ -88,6 +88,7 @@ list(APPEND XTOSKRNL_SOURCE
${XTOSKRNL_SOURCE_DIR}/rtl/llist.cc ${XTOSKRNL_SOURCE_DIR}/rtl/llist.cc
${XTOSKRNL_SOURCE_DIR}/rtl/math.cc ${XTOSKRNL_SOURCE_DIR}/rtl/math.cc
${XTOSKRNL_SOURCE_DIR}/rtl/memory.cc ${XTOSKRNL_SOURCE_DIR}/rtl/memory.cc
${XTOSKRNL_SOURCE_DIR}/rtl/rbtree.cc
${XTOSKRNL_SOURCE_DIR}/rtl/sha1.cc ${XTOSKRNL_SOURCE_DIR}/rtl/sha1.cc
${XTOSKRNL_SOURCE_DIR}/rtl/slist.cc ${XTOSKRNL_SOURCE_DIR}/rtl/slist.cc
${XTOSKRNL_SOURCE_DIR}/rtl/string.cc ${XTOSKRNL_SOURCE_DIR}/rtl/string.cc

View File

@@ -21,6 +21,7 @@
#include <rtl/llist.hh> #include <rtl/llist.hh>
#include <rtl/math.hh> #include <rtl/math.hh>
#include <rtl/memory.hh> #include <rtl/memory.hh>
#include <rtl/rbtree.hh>
#include <rtl/sha1.hh> #include <rtl/sha1.hh>
#include <rtl/slist.hh> #include <rtl/slist.hh>
#include <rtl/string.hh> #include <rtl/string.hh>

View File

@@ -0,0 +1,45 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/includes/rtl/rbtree.hh
* DESCRIPTION: Red-Black Tree implementation
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#ifndef __XTOSKRNL_RTL_RBTREE_HH
#define __XTOSKRNL_RTL_RBTREE_HH
#include <xtos.hh>
/* Runtime Library */
namespace RTL
{
class RedBlackTree
{
public:
STATIC XTAPI VOID InitializeTree(OUT PRTL_RB_TREE Tree);
STATIC XTAPI VOID InsertNode(IN PRTL_RB_TREE Tree,
IN PRTL_BALANCED_NODE Parent,
IN PRTL_BALANCED_NODE Node,
IN BOOLEAN RightChild);
STATIC XTAPI VOID RemoveNode(IN PRTL_RB_TREE Tree,
IN PRTL_BALANCED_NODE Node);
private:
STATIC XTAPI VOID CopyNodeColor(OUT PRTL_BALANCED_NODE Destination,
IN PRTL_BALANCED_NODE Source);
STATIC XTAPI RTL_BALANCED_NODE_COLOR GetNodeColor(IN PRTL_BALANCED_NODE Node);
STATIC XTAPI PRTL_BALANCED_NODE GetParentNode(PRTL_BALANCED_NODE Node);
STATIC XTAPI VOID RotateLeft(IN PRTL_RB_TREE Tree,
IN PRTL_BALANCED_NODE Node);
STATIC XTAPI VOID RotateRight(IN PRTL_RB_TREE Tree,
IN PRTL_BALANCED_NODE Node);
STATIC XTAPI VOID SetNodeColor(OUT PRTL_BALANCED_NODE Node,
IN RTL_BALANCED_NODE_COLOR Color);
STATIC XTAPI VOID SetParentNode(OUT PRTL_BALANCED_NODE Node,
IN PRTL_BALANCED_NODE Parent);
};
}
#endif /* __XTOSKRNL_RTL_RBTREE_HH */

723
xtoskrnl/rtl/rbtree.cc Normal file
View File

@@ -0,0 +1,723 @@
/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/rtl/rbtree.cc
* DESCRIPTION: Red-Black Tree implementation
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
*/
#include <xtos.hh>
/**
* Copies the color from the Source node to the Dest node without modifying the destination node's parent pointer.
*
* @param Destination
* Supplies a pointer to the balanced node for which to set the color.
*
* @param Source
* Supplies a pointer to the balanced node from which to copy the color.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
RTL::RedBlackTree::CopyNodeColor(OUT PRTL_BALANCED_NODE Destination,
IN PRTL_BALANCED_NODE Source)
{
/* Copy the color from the source node to the destination node */
Destination->ParentValue = (Destination->ParentValue & ~RTL_BALANCED_NODE_COLOR_MASK) | GetNodeColor(Source);
}
/**
* Extracts the color bit from the node's ParentValue.
*
* @param Node
* Supplies a pointer to the balanced node from which to extract the color.
*
* @return This routine returns the color of the given node, either NodeRed or NodeBlack.
*
* @since XT 1.0
*/
XTAPI
RTL_BALANCED_NODE_COLOR
RTL::RedBlackTree::GetNodeColor(IN PRTL_BALANCED_NODE Node)
{
/* Return the node color */
return (RTL_BALANCED_NODE_COLOR)(Node->ParentValue & RTL_BALANCED_NODE_COLOR_MASK);
}
/**
* Retrieves the parent node pointer by masking out the reserved bits.
*
* @param Node
* Supplies a pointer to the balanced node from which to extract the parent pointer.
*
* @return This routine returns a pointer to the parent node of the given node.
*
* @since XT 1.0
*/
XTAPI
PRTL_BALANCED_NODE
RTL::RedBlackTree::GetParentNode(IN PRTL_BALANCED_NODE Node)
{
/* Return the parent node pointer by masking out the reserved bits */
return (PRTL_BALANCED_NODE)(Node->ParentValue & ~RTL_BALANCED_NODE_RESERVED_PARENT_MASK);
}
/**
* Initializes a red-black tree by setting its root and minimum pointers to NULLPTR.
*
* @param Tree
* Supplies a pointer to the RTL_RB_TREE structure to initialize.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
RTL::RedBlackTree::InitializeTree(OUT PRTL_RB_TREE Tree)
{
/* Initialize the tree */
Tree->Root = NULLPTR;
Tree->Min = NULLPTR;
}
/**
* Inserts a new node into the red-black tree at the specified position and rebalances the tree.
*
* @param Tree
* Supplies a pointer to the RTL_RB_TREE structure into which the node is inserted.
*
* @param Parent
* Supplies a pointer to the parent node under which the new node will be inserted.
* If the tree is empty, this must be NULLPTR.
*
* @param Node
* Supplies a pointer to the uninitialized balanced node to insert into the tree.
*
* @param RightChild
* Specifies whether the new node should be inserted as the right child (TRUE)
* or the left child (FALSE) of the parent node.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
RTL::RedBlackTree::InsertNode(IN PRTL_RB_TREE Tree,
IN PRTL_BALANCED_NODE Parent,
IN PRTL_BALANCED_NODE Node,
IN BOOLEAN RightChild)
{
PRTL_BALANCED_NODE CurrentNode, CurrentParent, GrandParent, Uncle;
/* Initialize the new node with no children and default its color to red */
Node->Left = NULLPTR;
Node->Right = NULLPTR;
Node->ParentValue = (ULONG_PTR)Parent | NodeRed;
/* Check if the tree is not empty */
if(Parent != NULLPTR)
{
/* Determine whether to attach the node as a right or left child */
if(RightChild)
{
/* Attach the new node to the right side of the parent */
Parent->Right = Node;
}
else
{
/* Attach the new node to the left side of the parent */
Parent->Left = Node;
/* Check if the new node is placed left of the current minimum */
if(Parent == Tree->Min)
{
/* Update the cached minimum pointer for the tree */
Tree->Min = Node;
}
}
}
else
{
/* The tree was empty, so the new node becomes both the root and the minimum */
Tree->Root = Node;
Tree->Min = Node;
}
/* Begin fixing up the red-black tree properties */
CurrentNode = Node;
while(CurrentNode != Tree->Root && GetNodeColor(GetParentNode(CurrentNode)) == NodeRed)
{
/* Retrieve the parent and grandparent nodes to determine rotation and recoloring cases */
CurrentParent = GetParentNode(CurrentNode);
GrandParent = GetParentNode(CurrentParent);
/* Check if the parent is a left child of the grandparent */
if(CurrentParent == GrandParent->Left)
{
/* Determine the uncle node */
Uncle = GrandParent->Right;
if(Uncle != NULLPTR && GetNodeColor(Uncle) == NodeRed)
{
/* Recolor parent, uncle, and grandparent */
SetNodeColor(CurrentParent, NodeBlack);
SetNodeColor(Uncle, NodeBlack);
SetNodeColor(GrandParent, NodeRed);
/* Move the current node pointer up to the grandparent */
CurrentNode = GrandParent;
}
else
{
/* Check if current node is a right child */
if(CurrentNode == CurrentParent->Right)
{
/* Move the current pointer to the parent and perform a left rotation */
CurrentNode = CurrentParent;
RotateLeft(Tree, CurrentNode);
/* Update parent and grandparent pointers after the rotation */
CurrentParent = GetParentNode(CurrentNode);
GrandParent = GetParentNode(CurrentParent);
}
/* Recolor parent and grandparent */
SetNodeColor(CurrentParent, NodeBlack);
SetNodeColor(GrandParent, NodeRed);
/* Perform a right rotation around the grandparent to restore tree balance */
RotateRight(Tree, GrandParent);
}
}
else
{
/* Determine the uncle node */
Uncle = GrandParent->Left;
if(Uncle != NULLPTR && GetNodeColor(Uncle) == NodeRed)
{
/* Recolor parent, uncle, and grandparent */
SetNodeColor(CurrentParent, NodeBlack);
SetNodeColor(Uncle, NodeBlack);
SetNodeColor(GrandParent, NodeRed);
/* Move the current node pointer up to the grandparent */
CurrentNode = GrandParent;
}
else
{
/* Check if current node is a left child */
if(CurrentNode == CurrentParent->Left)
{
/* Move the current pointer to the parent and perform a right rotation */
CurrentNode = CurrentParent;
RotateRight(Tree, CurrentNode);
/* Update parent and grandparent pointers after the rotation */
CurrentParent = GetParentNode(CurrentNode);
GrandParent = GetParentNode(CurrentParent);
}
/* Recolor parent and grandparent */
SetNodeColor(CurrentParent, NodeBlack);
SetNodeColor(GrandParent, NodeRed);
/* Perform a left rotation around the grandparent to restore tree balance */
RotateLeft(Tree, GrandParent);
}
}
}
/* Ensure the root node is always colored black */
SetNodeColor(Tree->Root, NodeBlack);
}
/**
* Removes the specified node from the red-black tree and rebalances the tree to maintain its properties.
*
* @param Tree
* Supplies a pointer to the RTL_RB_TREE structure from which the node is removed.
*
* @param Node
* Supplies a pointer to the balanced node to remove from the tree.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
RTL::RedBlackTree::RemoveNode(IN PRTL_RB_TREE Tree,
IN PRTL_BALANCED_NODE Node)
{
PRTL_BALANCED_NODE CurrentNode, NextMinNode, NodeToRemove, ParentNode, Replacement, ReplacementParent, SiblingNode;
ULONG_PTR RemoveNodeColor;
/* Initialize variables to track the node */
NodeToRemove = Node;
RemoveNodeColor = GetNodeColor(NodeToRemove);
Replacement = NULLPTR;
ReplacementParent = NULLPTR;
/* Check if the node being removed is the cached minimum node */
if(Tree->Min == Node)
{
/* Find the next minimum node */
NextMinNode = Node->Right;
if(NextMinNode != NULLPTR)
{
/* Traverse to the leftmost descendant of the right child */
while(NextMinNode->Left != NULLPTR)
{
/* Move down to the left child */
NextMinNode = NextMinNode->Left;
}
/* Update the tree's minimum pointer to the found successor */
Tree->Min = NextMinNode;
}
else
{
/* The parent becomes the new minimum */
Tree->Min = GetParentNode(Node);
}
}
/* Check if the node to remove has no left child */
if(Node->Left == NULLPTR)
{
/* Use the right child as the replacement node */
Replacement = Node->Right;
ReplacementParent = GetParentNode(Node);
/* Check if the removed node was the root of the tree */
if(ReplacementParent == NULLPTR)
{
/* The replacement node becomes the new root */
Tree->Root = Replacement;
}
else if(Node == ReplacementParent->Left)
{
/* Link the replacement to the parent's left side */
ReplacementParent->Left = Replacement;
}
else
{
/* Link the replacement to the parent's right side */
ReplacementParent->Right = Replacement;
}
/* Check if replacement exists */
if(Replacement != NULLPTR)
{
/* Link the replacement back to its new parent */
SetParentNode(Replacement, ReplacementParent);
}
}
else if(Node->Right == NULLPTR)
{
/* Use the left child as the replacement node */
Replacement = Node->Left;
ReplacementParent = GetParentNode(Node);
/* Check if the removed node was the root of the tree */
if(ReplacementParent == NULLPTR)
{
/* The replacement node becomes the new root */
Tree->Root = Replacement;
}
else if(Node == ReplacementParent->Left)
{
/* Link the replacement to the parent's left side */
ReplacementParent->Left = Replacement;
}
else
{
/* Link the replacement to the parent's right side */
ReplacementParent->Right = Replacement;
}
/* Check if replacement exists */
if(Replacement != NULLPTR)
{
/* Link the replacement back to its new parent */
SetParentNode(Replacement, ReplacementParent);
}
}
else
{
/* Find the in-order successor to replace it */
NodeToRemove = Node->Right;
while(NodeToRemove->Left != NULLPTR)
{
/* Traverse to the leftmost node in the right subtree */
NodeToRemove = NodeToRemove->Left;
}
/* Cache the original color of the successor node */
RemoveNodeColor = GetNodeColor(NodeToRemove);
Replacement = NodeToRemove->Right;
ReplacementParent = GetParentNode(NodeToRemove);
/* Check fif the successor is not the direct right child of the node being removed */
if(NodeToRemove != Node->Right)
{
/* Detach the successor from its original parent and link its right child */
ReplacementParent->Left = Replacement;
if(Replacement != NULLPTR)
{
/* Link the successor's right child to the successor's parent */
SetParentNode(Replacement, ReplacementParent);
}
/* Attach the original node's right subtree to the successor */
NodeToRemove->Right = Node->Right;
SetParentNode(NodeToRemove->Right, NodeToRemove);
}
else
{
/* Set the replacement parent as the successor itself */
ReplacementParent = NodeToRemove;
}
/* Retrieve the parent of the node being removed to link it to the successor */
ParentNode = GetParentNode(Node);
if(ParentNode == NULLPTR)
{
/* The successor becomes the new root */
Tree->Root = NodeToRemove;
}
else if(Node == ParentNode->Left)
{
/* Link the successor to the left side of the original parent */
ParentNode->Left = NodeToRemove;
}
else
{
/* Link the successor to the right side of the original parent */
ParentNode->Right = NodeToRemove;
}
/* Update the parent pointer of the successor to its new parent */
SetParentNode(NodeToRemove, ParentNode);
NodeToRemove->Left = Node->Left;
/* Update the parent pointer of the left child and copy the original node's color */
SetParentNode(NodeToRemove->Left, NodeToRemove);
CopyNodeColor(NodeToRemove, Node);
}
/* Check if the physically removed node was black */
if(RemoveNodeColor == NodeBlack && Tree->Root != NULLPTR)
{
/* Fix up the tree properties */
CurrentNode = Replacement;
ParentNode = ReplacementParent;
/* Traverse up the tree */
while(CurrentNode != Tree->Root &&
(CurrentNode == NULLPTR || GetNodeColor(CurrentNode) == NodeBlack))
{
/* Check if the current node is a left child */
if(CurrentNode == ParentNode->Left)
{
/* Identify the sibling node on the right */
SiblingNode = ParentNode->Right;
/* Check if the sibling is red */
if(GetNodeColor(SiblingNode) == NodeRed)
{
/* Recolor the sibling to black */
SetNodeColor(SiblingNode, NodeBlack);
SetNodeColor(ParentNode, NodeRed);
/* Perform a left rotation around the parent */
RotateLeft(Tree, ParentNode);
SiblingNode = ParentNode->Right;
}
/* Check if both children of the sibling are black */
if((SiblingNode->Left == NULLPTR || GetNodeColor(SiblingNode->Left) == NodeBlack) &&
(SiblingNode->Right == NULLPTR || GetNodeColor(SiblingNode->Right) == NodeBlack))
{
/* Set the sibling color to red to restore black-height */
SetNodeColor(SiblingNode, NodeRed);
/* Move the current pointer up to the parent and continue checking */
CurrentNode = ParentNode;
ParentNode = GetParentNode(CurrentNode);
}
else
{
/* Check if the sibling's right child is black */
if(SiblingNode->Right == NULLPTR || GetNodeColor(SiblingNode->Right) == NodeBlack)
{
/* Check if the left child needs updating */
if(SiblingNode->Left != NULLPTR)
{
/* Recolor the sibling's left child */
SetNodeColor(SiblingNode->Left, NodeBlack);
}
/* Set the sibling to red and perform the right rotation */
SetNodeColor(SiblingNode, NodeRed);
RotateRight(Tree, SiblingNode);
SiblingNode = ParentNode->Right;
}
/* Swap colors between sibling and parent and recolor right child to black */
CopyNodeColor(SiblingNode, ParentNode);
SetNodeColor(ParentNode, NodeBlack);
/* Check if the right child needs updating */
if(SiblingNode->Right != NULLPTR)
{
/* Recolor the sibling's right child */
SetNodeColor(SiblingNode->Right, NodeBlack);
}
/* Perform a left rotation around the parent to restore balance */
RotateLeft(Tree, ParentNode);
CurrentNode = Tree->Root;
/* The tree properties are restored, terminate the loop */
break;
}
}
else
{
/* Process the case where the current node is a right child */
SiblingNode = ParentNode->Left;
/* Check if the sibling is red */
if(GetNodeColor(SiblingNode) == NodeRed)
{
/* Recolor the sibling to black */
SetNodeColor(SiblingNode, NodeBlack);
SetNodeColor(ParentNode, NodeRed);
/* Perform a right rotation around the parent */
RotateRight(Tree, ParentNode);
SiblingNode = ParentNode->Left;
}
/* Check if both children of the sibling are black */
if((SiblingNode->Right == NULLPTR || GetNodeColor(SiblingNode->Right) == NodeBlack) &&
(SiblingNode->Left == NULLPTR || GetNodeColor(SiblingNode->Left) == NodeBlack))
{
/* Set the sibling color to red to restore black-height */
SetNodeColor(SiblingNode, NodeRed);
CurrentNode = ParentNode;
ParentNode = GetParentNode(CurrentNode);
}
else
{
/* Check if the sibling's left child is black */
if(SiblingNode->Left == NULLPTR || GetNodeColor(SiblingNode->Left) == NodeBlack)
{
/* Check if the right child needs updating */
if(SiblingNode->Right != NULLPTR)
{
/* Recolor the sibling's right child */
SetNodeColor(SiblingNode->Right, NodeBlack);
}
/* Set the sibling to red and perform the right rotation */
SetNodeColor(SiblingNode, NodeRed);
RotateLeft(Tree, SiblingNode);
SiblingNode = ParentNode->Left;
}
/* Swap colors between sibling and parent and recolor right child to black */
CopyNodeColor(SiblingNode, ParentNode);
SetNodeColor(ParentNode, NodeBlack);
/* Check if the left child needs updating */
if(SiblingNode->Left != NULLPTR)
{
/* Recolor the sibling's left child */
SetNodeColor(SiblingNode->Left, NodeBlack);
}
/* Perform a right rotation around the parent */
RotateRight(Tree, ParentNode);
CurrentNode = Tree->Root;
/* The tree properties are restored, terminate the loop */
break;
}
}
}
/* Check if the current node is not null */
if(CurrentNode != NULLPTR)
{
/* Force the current node to be black to satisfy the red-black rules */
SetNodeColor(CurrentNode, NodeBlack);
}
}
}
/**
* Performs a left rotation around the specified node to maintain red-black tree balance.
*
* @param Tree
* Supplies a pointer to the RTL_RB_TREE structure containing the node.
*
* @param Node
* Supplies a pointer to the balanced node around which to perform the left rotation.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
RTL::RedBlackTree::RotateLeft(IN PRTL_RB_TREE Tree,
IN PRTL_BALANCED_NODE Node)
{
PRTL_BALANCED_NODE ParentNode, RightNode;
/* Establish the right child as the pivot node for the rotation */
RightNode = Node->Right;
Node->Right = RightNode->Left;
/* Transfer the left subtree of the pivot to the right subtree of the node */
if(RightNode->Left != NULLPTR)
{
/* Update the parent pointer */
SetParentNode(RightNode->Left, Node);
}
/* Update the parent */
ParentNode = GetParentNode(Node);
SetParentNode(RightNode, ParentNode);
/* Link the parent of the original node to the new pivot node */
if(ParentNode == NULLPTR)
{
/* Set the pivot new root */
Tree->Root = RightNode;
}
else if(Node == ParentNode->Left)
{
/* Update the left child pointer of the parent */
ParentNode->Left = RightNode;
}
else
{
/* Update the right child pointer of the parent */
ParentNode->Right = RightNode;
}
/* Place the original node as the left child of the pivot */
RightNode->Left = Node;
SetParentNode(Node, RightNode);
}
/**
* Performs a right rotation around the specified node to maintain red-black tree balance.
*
* @param Tree
* Supplies a pointer to the RTL_RB_TREE structure containing the node.
*
* @param Node
* Supplies a pointer to the balanced node around which to perform the right rotation.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
RTL::RedBlackTree::RotateRight(IN PRTL_RB_TREE Tree,
IN PRTL_BALANCED_NODE Node)
{
PRTL_BALANCED_NODE LeftNode, ParentNode;
/* Establish the left child as the pivot node for the rotation */
LeftNode = Node->Left;
Node->Left = LeftNode->Right;
/* Transfer the right subtree of the pivot to the left subtree of the node */
if(LeftNode->Right != NULLPTR)
{
/* Update the parent pointer */
SetParentNode(LeftNode->Right, Node);
}
/* Update the parent */
ParentNode = GetParentNode(Node);
SetParentNode(LeftNode, ParentNode);
/* Link the parent of the original node to the new pivot node */
if(ParentNode == NULLPTR)
{
/* Set the pivot new root */
Tree->Root = LeftNode;
}
else if(Node == ParentNode->Right)
{
/* Update the right child pointer of the parent */
ParentNode->Right = LeftNode;
}
else
{
/* Update the left child pointer of the parent */
ParentNode->Left = LeftNode;
}
/* Place the original node as the right child of the pivot */
LeftNode->Right = Node;
SetParentNode(Node, LeftNode);
}
/**
* Sets the node's color. Clears the color bit first, then applies the new color.
*
* @param Node
* Supplies a pointer to the balanced node for which to set the color.
*
* @param Color
* Specifies the new color to set for the node, either NodeRed or NodeBlack.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
RTL::RedBlackTree::SetNodeColor(OUT PRTL_BALANCED_NODE Node,
IN RTL_BALANCED_NODE_COLOR Color)
{
/* Set the node color */
Node->ParentValue = (Node->ParentValue & ~RTL_BALANCED_NODE_COLOR_MASK) | Color;
}
/**
* Sets the parent node pointer while preserving the current color bits.
*
* @param Node
* Supplies a pointer to the balanced node for which to set the parent pointer.
*
* @param Parent
* Supplies a pointer to the new parent node to be set for the given node.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTAPI
VOID
RTL::RedBlackTree::SetParentNode(OUT PRTL_BALANCED_NODE Node,
IN PRTL_BALANCED_NODE Parent)
{
/* Set the parent node pointer */
Node->ParentValue = ((ULONG_PTR)Parent & ~RTL_BALANCED_NODE_RESERVED_PARENT_MASK) |
(Node->ParentValue & RTL_BALANCED_NODE_RESERVED_PARENT_MASK);
}