added the red-black tree library code

This commit is contained in:
Eric J. Bowersox 2013-04-17 01:29:30 -06:00
parent 54529bc017
commit cf0e7ea2be
11 changed files with 562 additions and 4 deletions

View File

@ -0,0 +1,102 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#ifndef __RBTREE_H_INCLUDED
#define __RBTREE_H_INCLUDED
#ifndef __ASM__
#include <comrogue/types.h>
#include <comrogue/compiler_macros.h>
/*------------------------------------------------------------------------------------------------------
* An implementation of left-leaning red-black 2-3 trees as detailed in "Left-leaning Red-Black Trees,"
* Robert Sedgwick, Princeton University, 2008 (http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf).
* See also Java source at https://gist.github.com/741080.
*
* Note that we store the node color as a single bit in the low-order bit of the "right" node pointer.
* This is do-able since, for all cases, pointers to instances of RBTREENODE will be 4-byte aligned.
*------------------------------------------------------------------------------------------------------
*/
/* Generic key and comparison function definitions */
typedef PVOID TREEKEY;
typedef INT32 (*PFNTREECOMPARE)(TREEKEY, TREEKEY);
/* A node may be colored red or black. */
#define RED TRUE
#define BLACK FALSE
/* The basic tree node. */
typedef struct tagRBTREENODE {
struct tagRBTREENODE *ptnLeft; /* pointer to left child */
UINT_PTR ptnRightColor; /* pointer to right child AND color stored in low-order bit */
TREEKEY treekey; /* key value */
} RBTREENODE, *PRBTREENODE;
/* Tree node macros, mostly to access either color or pointer or both from the ptnRightColor field */
#define rbtNodeRight(ptn) ((PRBTREENODE)((ptn)->ptnRightColor & ~1))
#define rbtNodeColor(ptn) ((ptn)->ptnRightColor & 1)
#define rbtIsRed(ptn) ((ptn) ? rbtNodeColor(ptn) : FALSE)
#define rbtSetNodeRight(ptn, ptnRight) \
do { (ptn)->ptnRightColor = (((UINT_PTR)(ptnRight)) & ~1) | ((ptn)->ptnRightColor & 1); } while (0)
#define rbtSetNodeColor(ptn, clr) \
do { (ptn)->ptnRightColor = ((ptn)->ptnRightColor & ~1) | ((clr) ? 1 : 0); } while (0)
#define rbtToggleColor(ptn) do { if (ptn) (ptn)->ptnRightColor ^= 1; } while (0)
#define rbtInitNode(ptn, ptnLeft, ptnRight, clr, key) \
do { (ptn)->ptnLeft = (ptnLeft); (ptn)->ptnRightColor = (((UINT_PTR)(ptnRight)) & ~1) | ((clr) ? 1 : 0); \
(ptn)->treekey = (key); } while (0)
#define rbtNewNode(ptn, key) rbtInitNode(ptn, NULL, NULL, RED, key)
/* The head-of-tree structure. */
typedef struct tagRBTREE {
PFNTREECOMPARE pfnTreeCompare; /* pointer to comparison function */
PRBTREENODE ptnRoot; /* pointer to root of tree */
} RBTREE, *PRBTREE;
/* Macro to initialize the tree head. */
#define rbtInitTree(ptree, pfnCompare) \
do { (ptree)->pfnTreeCompare = (pfnCompare); (ptree)->ptnRoot = NULL; } while (0)
/* Function prototypes. */
CDECL_BEGIN
extern INT32 RbtStdCompareByValue(TREEKEY k1, TREEKEY k2);
extern void RbtInsert(PRBTREE ptree, PRBTREENODE ptnNew);
extern PRBTREENODE RbtFind(PRBTREE ptree, TREEKEY key);
extern PRBTREENODE RbtFindMin(PRBTREE ptree);
extern void RbtDelete(PRBTREE ptree, TREEKEY key);
CDECL_END
#endif /* __ASM__ */
#endif /* __RBTREE_H_INCLUDED */

View File

@ -38,6 +38,11 @@
#include <comrogue/types.h> #include <comrogue/types.h>
/*----------------------
* Segment declarations
*----------------------
*/
#ifdef __COMROGUE_PRESTART__ #ifdef __COMROGUE_PRESTART__
#define SEG_INIT_CODE __attribute__((__section__(".prestart.text"))) #define SEG_INIT_CODE __attribute__((__section__(".prestart.text")))
@ -58,9 +63,15 @@
#endif /* __COMROGUE_PRESTART__ */ #endif /* __COMROGUE_PRESTART__ */
#define DECLARE_INIT_STRING8_CONST(name, value) const CHAR SEG_INIT_RODATA name [] = value /*------------------------------------
#define DECLARE_LIB_STRING8_CONST(name, value) const CHAR SEG_LIB_RODATA name [] = value * String constant declaration macros
#define DECLARE_STRING8_CONST(name, value) const CHAR SEG_RODATA name [] = value *------------------------------------
*/
#define DECLARE_STRING8_CONST_STGCLASS(name, value, stgclass) const CHAR stgclass name [] = value
#define DECLARE_INIT_STRING8_CONST(name, value) DECLARE_STRING8_CONST_STGCLASS(name, value, SEG_INIT_RODATA)
#define DECLARE_LIB_STRING8_CONST(name, value) DECLARE_STRING8_CONST_STGCLASS(name, value, SEG_LIB_RODATA)
#define DECLARE_STRING8_CONST(name, value) DECLARE_STRING8_CONST_STGCLASS(name, value, SEG_RODATA)
#endif /* __ASM__ */ #endif /* __ASM__ */

View File

@ -90,8 +90,12 @@ CDECL_END
#if defined(__COMROGUE_PRESTART__) || defined(__COMROGUE_INIT__) #if defined(__COMROGUE_PRESTART__) || defined(__COMROGUE_INIT__)
#define DECLARE_THIS_FILE static DECLARE_INIT_STRING8_CONST(THIS_FILE, __FILE__); #define DECLARE_THIS_FILE static DECLARE_INIT_STRING8_CONST(THIS_FILE, __FILE__);
#else #else
#if defined(__COMROGUE_KERNEL_LIB__)
#define DECLARE_THIS_FILE static DECLARE_LIB_STRING8_CONST(THIS_FILE, __FILE__);
#else
#define DECLARE_THIS_FILE static DECLARE_STRING8_CONST(THIS_FILE, __FILE__); #define DECLARE_THIS_FILE static DECLARE_STRING8_CONST(THIS_FILE, __FILE__);
#endif #endif
#endif
#define ASSERT(x) ((x) ? (void)0 : ASSERT_FAIL_FUNC(THIS_FILE, __LINE__)) #define ASSERT(x) ((x) ? (void)0 : ASSERT_FAIL_FUNC(THIS_FILE, __LINE__))
#define VERIFY(x) ASSERT(x) #define VERIFY(x) ASSERT(x)

View File

@ -83,6 +83,8 @@ typedef unsigned long long uint64_t;
#define MAKEBOOL(val) ((val) ? TRUE : FALSE) #define MAKEBOOL(val) ((val) ? TRUE : FALSE)
#define OFFSETOF(struc, field) ((UINT_PTR)(&(((struc *)0)->field)))
#ifdef __COMROGUE_INTERNALS__ #ifdef __COMROGUE_INTERNALS__
/* Internal system types */ /* Internal system types */

View File

@ -48,7 +48,7 @@ AFLAGS = -mcpu=arm1176jzf-s -mfloat-abi=hard
ASM_CPP_FLAGS = $(INCLUDES) $(DEFS) -D__ASM__ ASM_CPP_FLAGS = $(INCLUDES) $(DEFS) -D__ASM__
PRESTART_OBJS = prestart.o early_trace.o collect_startup.o early_mm.o PRESTART_OBJS = prestart.o early_trace.o collect_startup.o early_mm.o
LIB_OBJS = divide.o qdivrem.o intlib.o objhelp.o str.o strcopymem.o strcomparemem.o strsetmem.o lib_guids.o LIB_OBJS = divide.o qdivrem.o intlib.o objhelp.o rbtree.o str.o strcopymem.o strcomparemem.o strsetmem.o lib_guids.o
RES_OBJS = lowlevel.o trace.o memmgr.o vmmap.o pagealloc.o RES_OBJS = lowlevel.o trace.o memmgr.o vmmap.o pagealloc.o
INIT_OBJS = start.o kistart.o init_heap.o INIT_OBJS = start.o kistart.o init_heap.o

View File

@ -29,6 +29,7 @@
* *
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation. * "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/ */
#define __COMROGUE_KERNEL_LIB__
#include <comrogue/types.h> #include <comrogue/types.h>
#include <comrogue/intlib.h> #include <comrogue/intlib.h>
#include <comrogue/internals/seg.h> #include <comrogue/internals/seg.h>

View File

@ -35,6 +35,7 @@
* AND in this order. * AND in this order.
*------------------------------------------------------------------------------------------------------ *------------------------------------------------------------------------------------------------------
*/ */
#define __COMROGUE_KERNEL_LIB__
#include <comrogue/internals/seg.h> #include <comrogue/internals/seg.h>
#define GUIDATTR SEG_LIB_RODATA #define GUIDATTR SEG_LIB_RODATA
#define INITGUID #define INITGUID

View File

@ -1,3 +1,35 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#define __COMROGUE_KERNEL_LIB__
#include <comrogue/types.h> #include <comrogue/types.h>
#include <comrogue/scode.h> #include <comrogue/scode.h>
#include <comrogue/str.h> #include <comrogue/str.h>

View File

@ -31,6 +31,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
/* Derived from FreeBSD libkern qdivrem.c, munged by Erbo to COMROGUE standards */ /* Derived from FreeBSD libkern qdivrem.c, munged by Erbo to COMROGUE standards */
#define __COMROGUE_KERNEL_LIB__
#include <comrogue/types.h> #include <comrogue/types.h>
#include <comrogue/internals/seg.h> #include <comrogue/internals/seg.h>
#include "quad.h" #include "quad.h"

403
kernel/rbtree.c Normal file
View File

@ -0,0 +1,403 @@
/*
* This file is part of the COMROGUE Operating System for Raspberry Pi
*
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
* All rights reserved.
*
* This program is free for commercial and non-commercial use as long as the following conditions are
* adhered to.
*
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
* in the code are not to be removed.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
* the following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/
#define __COMROGUE_KERNEL_LIB__
#include <comrogue/types.h>
#include <comrogue/internals/rbtree.h>
#include <comrogue/internals/seg.h>
#include <comrogue/internals/trace.h>
#ifdef THIS_FILE
#undef THIS_FILE
DECLARE_THIS_FILE
#endif
/*------------------------------------------------------------------------------------------------------
* An implementation of left-leaning red-black 2-3 trees as detailed in "Left-leaning Red-Black Trees,"
* Robert Sedgwick, Princeton University, 2008 (http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf).
* See also Java source at https://gist.github.com/741080.
*
* Note that we store the node color as a single bit in the low-order bit of the "right" node pointer.
* This is do-able since, for all cases, pointers to instances of RBTREENODE will be 4-byte aligned.
*------------------------------------------------------------------------------------------------------
*/
/*
* A standard compare-by-value function for tree keys, which compares the numeric values of the keys as
* unsigned integers.
*
* Parameters:
* - k1 = First key value to compare.
* - k2 = Second key value to compare.
*
* Returns:
* 0 if the keys are equal; an integer less than 0 if k1 is less than k2; an integer greater than 0 if
* k1 is greater than k2.
*/
SEG_LIB_CODE INT32 RbtStdCompareByValue(TREEKEY k1, TREEKEY k2)
{
if (k1 == k2)
return 0;
if (((UINT_PTR)k1) < ((UINT_PTR)k2))
return -1;
return 1;
}
/*
* Rotates a subtree "leftward," so that the root node of the tree is the former root node's right child.
* The new root node inherits the former root node's color, and the former root node turns red.
*
* Parameters:
* - ptn = Pointer to the root node of the subtree.
*
* Returns:
* Pointer to the new root node of the subtree after the rotation.
*/
SEG_LIB_CODE static PRBTREENODE rotate_left(PRBTREENODE ptn)
{
register PRBTREENODE ptnNewRoot = rbtNodeRight(ptn);
ASSERT(ptnNewRoot);
rbtSetNodeRight(ptn, ptnNewRoot->ptnLeft);
ptnNewRoot->ptnLeft = ptn;
rbtSetNodeColor(ptnNewRoot, rbtNodeColor(ptn));
rbtSetNodeColor(ptn, RED);
return ptnNewRoot;
}
/*
* Rotates a subtree "rightward," so that the root node of the tree is the former root node's left child.
* The new root node inherits the former root node's color, and the former root node turns red.
*
* Parameters:
* - ptn = Pointer to theroot node of the subtree.
*
* Returns:
* Pointer to the new root node of the subtree after the rotation.
*/
SEG_LIB_CODE static PRBTREENODE rotate_right(PRBTREENODE ptn)
{
register PRBTREENODE ptnNewRoot = ptn->ptnLeft;
ASSERT(ptnNewRoot);
ptn->ptnLeft = rbtNodeRight(ptnNewRoot);
rbtSetNodeRight(ptnNewRoot, ptn);
rbtSetNodeColor(ptnNewRoot, rbtNodeColor(ptn));
rbtSetNodeColor(ptn, RED);
return ptnNewRoot;
}
/*
* Flips the color of the specified node and both its immediate children.
*
* Parameters:
* - ptn = Pointer to the node to be color-flipped.
*
* Returns:
* Nothing.
*/
SEG_LIB_CODE static void color_flip(PRBTREENODE ptn)
{
rbtToggleColor(ptn);
rbtToggleColor(ptn->ptnLeft);
rbtToggleColor(rbtNodeRight(ptn));
}
/*
* Fixes up the given subtree after an insertion or deletion, to ensure that it maintains the invariants
* that no two consecutive links in the tree may be red, and that all red links must lean left.
*
* Parameters:
* - ptn = Pointer to the root node of the subtree to be fixed up.
*
* Returns:
* Pointer to the new root node of the subtree after fixup is performed.
*/
SEG_LIB_CODE static PRBTREENODE fix_up(PRBTREENODE ptn)
{
if (rbtIsRed(rbtNodeRight(ptn)) && !rbtIsRed(ptn->ptnLeft))
ptn = rotate_left(ptn);
if (rbtIsRed(ptn->ptnLeft) && rbtIsRed(ptn->ptnLeft->ptnLeft))
ptn = rotate_right(ptn);
if (rbtIsRed(ptn->ptnLeft) && rbtIsRed(rbtNodeRight(ptn)))
color_flip(ptn);
return ptn;
}
/*
* Inserts a new node under the current subtree. An O(log n) operation.
*
* Parameters:
* - ptree = Pointer to the tree head structure, containing the compare function.
* - ptnCurrent = Pointer to the current subtree we're inserting into.
* - ptnNew = Pointer to the new tree node to be inserted. This node must have been initialized with
* the rbtInitNode macro to contain a key, NULL left and right pointers, and be red. It is
* assumed that the node's key does NOT already exist in the tree.
*
* Returns:
* The pointer to the new subtree after the insertion is performed.
*
* N.B.:
* This function is recursive; however, the nature of the tree guarantees that the stack space consumed
* by its stack frames will be O(log n).
*/
SEG_LIB_CODE static PRBTREENODE insert_under(PRBTREE ptree, PRBTREENODE ptnCurrent, PRBTREENODE ptnNew)
{
register int cmp; /* compare result */
if (!ptnCurrent)
return ptnNew; /* degenerate case */
cmp = (*(ptree->pfnTreeCompare))(ptnNew->treekey, ptnCurrent->treekey);
ASSERT(cmp != 0);
if (cmp < 0)
ptnCurrent->ptnLeft = insert_under(ptree, ptnCurrent->ptnLeft, ptnNew);
else
rbtSetNodeRight(ptnCurrent, insert_under(ptree, rbtNodeRight(ptnCurrent), ptnNew));
return fix_up(ptnCurrent);
}
/*
* Inserts a new node into the tree. An O(log n) operation.
*
* Parameters:
* - ptree = Pointer to the tree head structure.
* - ptnNew = Pointer to the new tree node to be inserted. This node must have been initialized with
* the rbtInitNode macro to contain a key, NULL left and right pointers, and be red. It is
* assumed that the node's key does NOT already exist in the tree.
*
* Returns:
* Nothing.
*/
SEG_LIB_CODE void RbtInsert(PRBTREE ptree, PRBTREENODE ptnNew)
{
ptree->ptnRoot = insert_under(ptree, ptree->ptnRoot, ptnNew);
rbtSetNodeColor(ptree->ptnRoot, BLACK);
}
/*
* Locates a node in the tree by key. An O(log n) operation.
*
* Parameters:
* - ptree = Pointer to the tree head structure.
* - key = Key value to be looked up.
*
* Returns:
* Pointer to the node where the key is found, or NULL if not found.
*/
SEG_LIB_CODE PRBTREENODE RbtFind(PRBTREE ptree, TREEKEY key)
{
register PRBTREENODE ptn = ptree->ptnRoot; /* current node */
register int cmp; /* compare result */
while (ptn)
{
cmp = (*(ptree->pfnTreeCompare))(key, ptn->treekey);
if (cmp == 0)
break; /* found */
else if (cmp < 0)
ptn = ptn->ptnLeft;
else
ptn = rbtNodeRight(ptn);
}
return ptn;
}
/*
* Finds the "minimum" node in the subtree (the one at the bottom end of the left spine of the subtree).
*
* Parameters:
* - ptn = Pointer to the subtree to be searched.
*
* Returns:
* Pointer to the leftmost node in the subtree.
*/
SEG_LIB_CODE static PRBTREENODE find_min(PRBTREENODE ptn)
{
while (ptn->ptnLeft)
ptn = ptn->ptnLeft;
return ptn;
}
/*
* Finds the "minimum" node int he tree (the one at the bottom end of the left spine of the tree).
*
* Parameters:
* - ptree = Pointer to the tree head structure.
*
* Returns:
* Pointer to the leftmost node in the tree. If the tree has no nodes, NULL is returned.
*/
SEG_LIB_CODE PRBTREENODE RbtFindMin(PRBTREE ptree)
{
return ptree->ptnRoot ? find_min(ptree->ptnRoot) : NULL;
}
/*
* Fixup required to delete the leftmost node; we maintain the invariant that either the current node
* or its left child is red. After a color flip, we resolve any successive reds on the right with rotations
* and another color flip.
*
* Parameters:
* - ptn = Pointer to root of subtree to be fixed up.
*
* Returns:
* Pointer to root of subtree after fixup.
*/
SEG_LIB_CODE static PRBTREENODE move_red_left(PRBTREENODE ptn)
{
color_flip(ptn);
if (rbtNodeRight(ptn) && rbtIsRed(rbtNodeRight(ptn)->ptnLeft))
{
rbtSetNodeRight(ptn, rotate_right(rbtNodeRight(ptn)));
ptn = rotate_left(ptn);
color_flip(ptn);
}
return ptn;
}
/*
* Fixup required to delete an internal node, rotating left-leaning red links to the right.
*
* Parameters:
* - ptn = Pointer to root of subtree to be fixed up.
*
* Returns:
* Pointer to root of subtree after fixup.
*/
SEG_LIB_CODE static PRBTREENODE move_red_right(PRBTREENODE ptn)
{
color_flip(ptn);
if (ptn->ptnLeft && rbtIsRed(ptn->ptnLeft->ptnLeft))
{
ptn = rotate_right(ptn);
color_flip(ptn);
}
return ptn;
}
/*
* Deletes the leftmost node in the subtree. (Note that "deletes" means "removes from the tree." No memory
* delete operation is actually performed.)
*
* Parameters:
* - ptn = Pointer to root of subtree to have its leftmost node deleted.
*
* Returns:
* Pointer to root of subtree after having the leftmost node deleted.
*
* N.B.:
* This function is recursive; however, the nature of the tree guarantees that the stack space consumed
* by its stack frames will be O(log n).
*/
SEG_LIB_CODE static PRBTREENODE delete_min(PRBTREENODE ptn)
{
if (!(ptn->ptnLeft))
return rbtNodeRight(ptn);
if (!rbtIsRed(ptn->ptnLeft) && !rbtIsRed(ptn->ptnLeft->ptnLeft))
ptn = move_red_left(ptn);
ptn->ptnLeft = delete_min(ptn->ptnLeft);
return fix_up(ptn);
}
/*
* Detetes the node in the subtree having an arbitrary key. An O(log n) operation.
*
* Parameters:
* - ptree = Pointer to the tree head structure, containing the compare function.
* - ptnCurrent = Pointer to the root of the current subtree we're deleting from.
* - key = Key value we're deleting from the tree. It is assumed that this key value exists in the subtree.
*
* Returns:
* Pointer to the root of the subtree after the node has been deleted.
*
* N.B.:
* This function is recursive; however, the nature of the tree guarantees that the stack space consumed
* by its stack frames (and those of delete_min, where we call it) will be O(log n).
*/
SEG_LIB_CODE static PRBTREENODE delete_from_under(PRBTREE ptree, PRBTREENODE ptnCurrent, TREEKEY key)
{
register int cmp = (*(ptree->pfnTreeCompare))(key, ptnCurrent->treekey);
if (cmp < 0)
{
/* hunt down the left subtree */
if (!rbtIsRed(ptnCurrent->ptnLeft) && !rbtIsRed(ptnCurrent->ptnLeft->ptnLeft))
ptnCurrent = move_red_left(ptnCurrent);
ptnCurrent->ptnLeft = delete_from_under(ptree, ptnCurrent->ptnLeft, key);
}
else
{
if (rbtIsRed(ptnCurrent->ptnLeft))
{
ptnCurrent = rotate_right(ptnCurrent);
cmp = (*(ptree->pfnTreeCompare))(key, ptnCurrent->treekey);
}
if ((cmp == 0) && !rbtNodeRight(ptnCurrent))
return ptnCurrent->ptnLeft; /* degenerate case */
if ( !rbtIsRed(rbtNodeRight(ptnCurrent))
&& (!rbtNodeRight(ptnCurrent) || !rbtIsRed(rbtNodeRight(ptnCurrent)->ptnLeft)))
{
ptnCurrent = move_red_right(ptnCurrent);
cmp = (*(ptree->pfnTreeCompare))(key, ptnCurrent->treekey);
}
if (cmp == 0)
{
/*
* Here we find the minimum node in the right subtree, unlink it, and link it into place in place of
* ptnCurrent (i.e. node pointed to by ptnCurrent should no longer be referenced). We inherit the
* child pointers and color of ptnCurrent (minus the reference from the right-hand tree where applicable).
*/
register PRBTREENODE ptnMin = find_min(rbtNodeRight(ptnCurrent));
rbtSetNodeRight(ptnMin, delete_min(rbtNodeRight(ptnCurrent)));
ptnMin->ptnLeft = ptnCurrent->ptnLeft;
rbtSetNodeColor(ptnMin, rbtNodeColor(ptnCurrent));
ptnCurrent = ptnMin;
}
else /* hunt down the right subtree */
rbtSetNodeRight(ptnCurrent, delete_from_under(ptree, rbtNodeRight(ptnCurrent), key));
}
return fix_up(ptnCurrent);
}
/*
* Detetes the node in the tree having an arbitrary key. An O(log n) operation.
*
* Parameters:
* - ptree = Pointer to the tree head structure.
* - key = Key value we're deleting from the tree. It is assumed that this key value exists in the subtree.
*
* Returns:
* Nothing.
*/
SEG_LIB_CODE void RbtDelete(PRBTREE ptree, TREEKEY key)
{
ptree->ptnRoot = delete_from_under(ptree, ptree->ptnRoot, key);
if (ptree->ptnRoot)
rbtSetNodeColor(ptree->ptnRoot, BLACK);
}

View File

@ -29,6 +29,7 @@
* *
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation. * "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
*/ */
#define __COMROGUE_KERNEL_LIB__
#include <comrogue/types.h> #include <comrogue/types.h>
#include <comrogue/scode.h> #include <comrogue/scode.h>
#include <comrogue/intlib.h> #include <comrogue/intlib.h>