added the red-black tree library code
This commit is contained in:
parent
54529bc017
commit
cf0e7ea2be
102
include/comrogue/internals/rbtree.h
Normal file
102
include/comrogue/internals/rbtree.h
Normal 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 */
|
|
@ -38,6 +38,11 @@
|
|||
|
||||
#include <comrogue/types.h>
|
||||
|
||||
/*----------------------
|
||||
* Segment declarations
|
||||
*----------------------
|
||||
*/
|
||||
|
||||
#ifdef __COMROGUE_PRESTART__
|
||||
|
||||
#define SEG_INIT_CODE __attribute__((__section__(".prestart.text")))
|
||||
|
@ -58,9 +63,15 @@
|
|||
|
||||
#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
|
||||
#define DECLARE_STRING8_CONST(name, value) const CHAR SEG_RODATA name [] = value
|
||||
/*------------------------------------
|
||||
* String constant declaration macros
|
||||
*------------------------------------
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
|
||||
|
|
|
@ -90,8 +90,12 @@ CDECL_END
|
|||
#if defined(__COMROGUE_PRESTART__) || defined(__COMROGUE_INIT__)
|
||||
#define DECLARE_THIS_FILE static DECLARE_INIT_STRING8_CONST(THIS_FILE, __FILE__);
|
||||
#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__);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define ASSERT(x) ((x) ? (void)0 : ASSERT_FAIL_FUNC(THIS_FILE, __LINE__))
|
||||
#define VERIFY(x) ASSERT(x)
|
||||
|
|
|
@ -83,6 +83,8 @@ typedef unsigned long long uint64_t;
|
|||
|
||||
#define MAKEBOOL(val) ((val) ? TRUE : FALSE)
|
||||
|
||||
#define OFFSETOF(struc, field) ((UINT_PTR)(&(((struc *)0)->field)))
|
||||
|
||||
#ifdef __COMROGUE_INTERNALS__
|
||||
|
||||
/* Internal system types */
|
||||
|
|
|
@ -48,7 +48,7 @@ AFLAGS = -mcpu=arm1176jzf-s -mfloat-abi=hard
|
|||
ASM_CPP_FLAGS = $(INCLUDES) $(DEFS) -D__ASM__
|
||||
|
||||
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
|
||||
INIT_OBJS = start.o kistart.o init_heap.o
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
*
|
||||
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||
*/
|
||||
#define __COMROGUE_KERNEL_LIB__
|
||||
#include <comrogue/types.h>
|
||||
#include <comrogue/intlib.h>
|
||||
#include <comrogue/internals/seg.h>
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
* AND in this order.
|
||||
*------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
#define __COMROGUE_KERNEL_LIB__
|
||||
#include <comrogue/internals/seg.h>
|
||||
#define GUIDATTR SEG_LIB_RODATA
|
||||
#define INITGUID
|
||||
|
|
|
@ -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/scode.h>
|
||||
#include <comrogue/str.h>
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
/* Derived from FreeBSD libkern qdivrem.c, munged by Erbo to COMROGUE standards */
|
||||
#define __COMROGUE_KERNEL_LIB__
|
||||
#include <comrogue/types.h>
|
||||
#include <comrogue/internals/seg.h>
|
||||
#include "quad.h"
|
||||
|
|
403
kernel/rbtree.c
Normal file
403
kernel/rbtree.c
Normal 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);
|
||||
}
|
|
@ -29,6 +29,7 @@
|
|||
*
|
||||
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||
*/
|
||||
#define __COMROGUE_KERNEL_LIB__
|
||||
#include <comrogue/types.h>
|
||||
#include <comrogue/scode.h>
|
||||
#include <comrogue/intlib.h>
|
||||
|
|
Loading…
Reference in New Issue
Block a user