Implement red-black tree algorithm
This commit is contained in:
@@ -14,51 +14,55 @@
|
||||
|
||||
|
||||
/* UUID string lengths */
|
||||
#define GUID_STRING_LENGTH 38
|
||||
#define PARTUUID_STRING_LENGTH 13
|
||||
#define GUID_STRING_LENGTH 38
|
||||
#define PARTUUID_STRING_LENGTH 13
|
||||
|
||||
/* Maximum double/integer value string length */
|
||||
#define MAX_DOUBLE_STRING_SIZE 15
|
||||
#define MAX_INTEGER_STRING_SIZE 25
|
||||
#define MAX_DOUBLE_STRING_SIZE 15
|
||||
#define MAX_INTEGER_STRING_SIZE 25
|
||||
|
||||
/* Floating point definitions */
|
||||
#define DOUBLE_EXPONENT_MASK 0x7FF0000000000000ULL
|
||||
#define DOUBLE_EXPONENT_SHIFT 0x34
|
||||
#define DOUBLE_EXPONENT_BIAS 0x3FF
|
||||
#define DOUBLE_HIGH_VALUE_MASK 0x000FFFFF
|
||||
#define DOUBLE_HIGH_VALUE_SHIFT 0x20
|
||||
#define DOUBLE_PRECISION 6
|
||||
#define DOUBLE_HEX_PRECISION 13
|
||||
#define DOUBLE_SCIENTIFIC_PRECISION -4
|
||||
#define DOUBLE_SIGN_BIT 0x8000000000000000ULL
|
||||
#define DOUBLE_EXPONENT_MASK 0x7FF0000000000000ULL
|
||||
#define DOUBLE_EXPONENT_SHIFT 0x34
|
||||
#define DOUBLE_EXPONENT_BIAS 0x3FF
|
||||
#define DOUBLE_HIGH_VALUE_MASK 0x000FFFFF
|
||||
#define DOUBLE_HIGH_VALUE_SHIFT 0x20
|
||||
#define DOUBLE_PRECISION 6
|
||||
#define DOUBLE_HEX_PRECISION 13
|
||||
#define DOUBLE_SCIENTIFIC_PRECISION -4
|
||||
#define DOUBLE_SIGN_BIT 0x8000000000000000ULL
|
||||
|
||||
/* Print flag definitions */
|
||||
#define PFL_ALWAYS_PRINT_SIGN 0x00000001
|
||||
#define PFL_SPACE_FOR_PLUS 0x00000002
|
||||
#define PFL_LEFT_JUSTIFIED 0x00000004
|
||||
#define PFL_LEADING_ZEROES 0x00000008
|
||||
#define PFL_LONG_INTEGER 0x00000010
|
||||
#define PFL_LONG_DOUBLE 0x00000020
|
||||
#define PFL_WIDE_CHARACTER 0x00000040
|
||||
#define PFL_SHORT_VALUE 0x00000080
|
||||
#define PFL_UNSIGNED 0x00000100
|
||||
#define PFL_UPPERCASE 0x00000200
|
||||
#define PFL_PRINT_RADIX 0x00000400
|
||||
#define PFL_FLOAT_FORMAT 0x00000800
|
||||
#define PFL_SCI_FORMAT 0x00001000
|
||||
#define PFL_DIGIT_PRECISION 0x00002000
|
||||
#define PFL_THOUSANDS_GROUPING 0x00004000
|
||||
#define PFL_ALWAYS_PRINT_SIGN 0x00000001
|
||||
#define PFL_SPACE_FOR_PLUS 0x00000002
|
||||
#define PFL_LEFT_JUSTIFIED 0x00000004
|
||||
#define PFL_LEADING_ZEROES 0x00000008
|
||||
#define PFL_LONG_INTEGER 0x00000010
|
||||
#define PFL_LONG_DOUBLE 0x00000020
|
||||
#define PFL_WIDE_CHARACTER 0x00000040
|
||||
#define PFL_SHORT_VALUE 0x00000080
|
||||
#define PFL_UNSIGNED 0x00000100
|
||||
#define PFL_UPPERCASE 0x00000200
|
||||
#define PFL_PRINT_RADIX 0x00000400
|
||||
#define PFL_FLOAT_FORMAT 0x00000800
|
||||
#define PFL_SCI_FORMAT 0x00001000
|
||||
#define PFL_DIGIT_PRECISION 0x00002000
|
||||
#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 */
|
||||
#define SHA1_BLOCK_SIZE 64
|
||||
#define SHA1_DIGEST_SIZE 20
|
||||
#define SHA1_BLOCK_SIZE 64
|
||||
#define SHA1_DIGEST_SIZE 20
|
||||
|
||||
/* Time related definitions */
|
||||
#define TIME_SECONDS_PER_MINUTE 60
|
||||
#define TIME_SECONDS_PER_HOUR 3600
|
||||
#define TIME_SECONDS_PER_DAY 86400
|
||||
#define TIME_TICKS_PER_SECOND 10000000
|
||||
#define TIME_TICKS_PER_MILLISECOND 10000
|
||||
#define TIME_SECONDS_PER_MINUTE 60
|
||||
#define TIME_SECONDS_PER_HOUR 3600
|
||||
#define TIME_SECONDS_PER_DAY 86400
|
||||
#define TIME_TICKS_PER_SECOND 10000000
|
||||
#define TIME_TICKS_PER_MILLISECOND 10000
|
||||
|
||||
|
||||
/* C/C++ specific code */
|
||||
@@ -68,6 +72,13 @@
|
||||
typedef XTSTATUS (*PWRITE_CHARACTER)(IN CHAR 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 */
|
||||
typedef enum _RTL_VARIABLE_TYPE
|
||||
{
|
||||
@@ -84,6 +95,26 @@ typedef enum _RTL_VARIABLE_TYPE
|
||||
TypeWideString
|
||||
} 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 */
|
||||
typedef struct _RTL_BITMAP
|
||||
{
|
||||
@@ -110,12 +141,19 @@ typedef struct _RTL_PRINT_FORMAT_PROPERTIES
|
||||
LONG Flags;
|
||||
} 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 */
|
||||
typedef struct _RTL_SHA1_CONTEXT
|
||||
{
|
||||
ULONG State[5];
|
||||
ULONG Count[2];
|
||||
UCHAR Buffer[SHA1_BLOCK_SIZE];
|
||||
ULONG State[5];
|
||||
ULONG Count[2];
|
||||
UCHAR Buffer[SHA1_BLOCK_SIZE];
|
||||
} RTL_SHA1_CONTEXT, *PRTL_SHA1_CONTEXT;
|
||||
|
||||
/* Runtime time fields structure definition */
|
||||
|
||||
@@ -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 _MMSYSTEM_PTE_POOL_TYPE MMSYSTEM_PTE_POOL_TYPE, *PMMSYSTEM_PTE_POOL_TYPE;
|
||||
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 _SYSTEM_FIRMWARE_TYPE SYSTEM_FIRMWARE_TYPE, *PSYSTEM_FIRMWARE_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 _PROCESSOR_IDENTITY PROCESSOR_IDENTITY, *PPROCESSOR_IDENTITY;
|
||||
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_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_RB_TREE RTL_RB_TREE, *PRTL_RB_TREE;
|
||||
typedef struct _SINGLE_LIST_ENTRY SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY;
|
||||
typedef struct _SMBIOS_TABLE_HEADER SMBIOS_TABLE_HEADER, *PSMBIOS_TABLE_HEADER;
|
||||
typedef struct _SMBIOS3_TABLE_HEADER SMBIOS3_TABLE_HEADER, *PSMBIOS3_TABLE_HEADER;
|
||||
|
||||
@@ -88,6 +88,7 @@ list(APPEND XTOSKRNL_SOURCE
|
||||
${XTOSKRNL_SOURCE_DIR}/rtl/llist.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/rtl/math.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/rtl/memory.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/rtl/rbtree.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/rtl/sha1.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/rtl/slist.cc
|
||||
${XTOSKRNL_SOURCE_DIR}/rtl/string.cc
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <rtl/llist.hh>
|
||||
#include <rtl/math.hh>
|
||||
#include <rtl/memory.hh>
|
||||
#include <rtl/rbtree.hh>
|
||||
#include <rtl/sha1.hh>
|
||||
#include <rtl/slist.hh>
|
||||
#include <rtl/string.hh>
|
||||
|
||||
45
xtoskrnl/includes/rtl/rbtree.hh
Normal file
45
xtoskrnl/includes/rtl/rbtree.hh
Normal 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
723
xtoskrnl/rtl/rbtree.cc
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user