From 789a03329155068a3fd25a6814ad2cfa1d15b9e4 Mon Sep 17 00:00:00 2001 From: Art Yerkes Date: Sat, 14 Oct 2006 17:29:41 +0000 Subject: [PATCH] Fixed avl tree completely. - We can't use the builtin node as a sentinel in exactly the same way as used in the austin lib, so we account for that by treating the builtin node like nil a few places. svn path=/trunk/; revision=24510 --- reactos/lib/rtl/austin/avl.c | 66 +++++++++++++++++++++++++++++----- reactos/lib/rtl/austin/avl.h | 1 + reactos/lib/rtl/austin/tree.c | 15 +++++--- reactos/lib/rtl/generictable.c | 7 +++- 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/reactos/lib/rtl/austin/avl.c b/reactos/lib/rtl/austin/avl.c index 2c8a188bf51..de12d9b4efd 100644 --- a/reactos/lib/rtl/austin/avl.c +++ b/reactos/lib/rtl/austin/avl.c @@ -34,6 +34,38 @@ #define LESS GenericLessThan #define GREATER GenericGreaterThan +void print_node(udict_t *ud, udict_node_t *node, int indent) +{ + int i; + char buf[100]; + udict_node_t *nil = ud->BalancedRoot.Parent; + + for( i = 0; i < indent; i++ ) buf[i] = ' '; + if( node == ud->BalancedRoot.Parent ) { + sprintf(buf+i, "Nil\n"); + DbgPrint("%s", buf); + } else { + sprintf(buf+i, "Node %x (parent %x: balance %d)\n", (int)node, (int)node->parent, node->Balance); + DbgPrint("%s", buf); + if( node->LeftChild != nil ) { + sprintf(buf+i, "--> Left\n"); + DbgPrint("%s", buf); + print_node(ud, node->LeftChild, indent+1); + } + if( node->RightChild != nil ) { + sprintf(buf+i, "--> Right\n"); + DbgPrint("%s", buf); + print_node(ud, node->RightChild, indent+1); + } + } +} + +void print_tree(udict_t *ud) +{ + DbgPrint("TREE %x (Nil %x)\n", ud, ud->BalancedRoot.Parent); + print_node(ud, &ud->BalancedRoot, 0); +} + void avl_init(udict_t *ud) { ud->BalancedRoot.left = ud->BalancedRoot.right = @@ -43,7 +75,12 @@ void avl_init(udict_t *ud) ud->BalancedRoot.parent->parent = ud->BalancedRoot.parent; } -void RotateLeft(udict_node_t **top) +void avl_deinit(udict_t *ud) +{ + ud->FreeRoutine(ud, ud->BalancedRoot.parent); +} + +static void RotateLeft(udict_node_t **top) { udict_node_t *parent = *top; udict_node_t *child = parent->right; @@ -56,7 +93,7 @@ void RotateLeft(udict_node_t **top) *top = child; }/*RotateLeft*/ -void RotateRight(udict_node_t **top) +static void RotateRight(udict_node_t **top) { udict_node_t *parent = *top; udict_node_t *child = parent->left; @@ -69,7 +106,7 @@ void RotateRight(udict_node_t **top) *top = child; }/*RotateRight*/ -void FixBalance(udict_node_t **pnode, udict_avl_balance_t bal) +static void FixBalance(udict_node_t **pnode, udict_avl_balance_t bal) { udict_node_t *node = *pnode; udict_node_t *child; @@ -157,7 +194,7 @@ void FixBalance(udict_node_t **pnode, udict_avl_balance_t bal) }/*else*/ }/*FixBalance*/ -int Insert(udict_t *ud, udict_node_t *what, udict_node_t **where, udict_node_t *parent) +static int Insert(udict_t *ud, udict_node_t *what, udict_node_t **where, udict_node_t *parent) { udict_node_t *here = *where; int result; @@ -170,6 +207,8 @@ int Insert(udict_t *ud, udict_node_t *what, udict_node_t **where, udict_node_t * else { result = ud->compare(ud, key(what), key(here)); + assert (result != GenericEqual); + if (result == LESS) { if (Insert(ud, what, &here->left, here)) { /* @@ -204,6 +243,13 @@ void avl_insert_node(udict_t *ud, udict_node_t *node) nil->balance = LEFTHEAVY; }/*if*/ + if (ud->BalancedRoot.left == node) { + node->parent = &ud->BalancedRoot; + ud->BalancedRoot.balance = LEFTHEAVY; + } + + print_tree(ud); + ud->nodecount++; } @@ -263,7 +309,6 @@ void avl_delete_node(udict_t *ud, udict_node_t *node) while (parent != nil) { if ((parent->left == nil) && (parent->right == nil)) { assert (child == nil); - assert (parent->balance != BALANCED); parent->balance = BALANCED; /* propagate height reduction to upper level */ }/*if*/ @@ -299,7 +344,7 @@ void avl_delete_node(udict_t *ud, udict_node_t *node) else break; }/*while*/ -}/*avl_delete*/ +}/*avl_delete_node*/ void *avl_get_data(udict_node_t *here) { return data(here); @@ -337,7 +382,8 @@ int avl_search(udict_t *ud, void *_key, udict_node_t *here, udict_node_t **where int avl_is_nil(udict_t *ud, udict_node_t *node) { - return tree_null_priv(ud) == node; + return tree_null_priv(ud) == node || + &ud->BalancedRoot == node; } udict_node_t *avl_first(udict_t *ud) @@ -352,5 +398,9 @@ udict_node_t *avl_last(udict_t *ud) udict_node_t *avl_next(udict_t *ud, udict_node_t *prev) { - return udict_tree_next(ud, prev); + udict_node_t *node = udict_tree_next(ud, prev); + if( node == tree_null_priv(ud) || node == &ud->BalancedRoot ) + return NULL; + else + return node; } diff --git a/reactos/lib/rtl/austin/avl.h b/reactos/lib/rtl/austin/avl.h index d5ad0b22f3d..43f2d9ec48b 100644 --- a/reactos/lib/rtl/austin/avl.h +++ b/reactos/lib/rtl/austin/avl.h @@ -12,6 +12,7 @@ #define avl_data(x) ((void*)(&(x)[1])) void avl_init(PRTL_AVL_TABLE table); +void avl_deinit(PRTL_AVL_TABLE table); void avl_insert_node(PRTL_AVL_TABLE table, PRTL_BALANCED_LINKS node); void avl_delete_node(PRTL_AVL_TABLE table, PRTL_BALANCED_LINKS node); int avl_is_nil(PRTL_AVL_TABLE table, PRTL_BALANCED_LINKS node); diff --git a/reactos/lib/rtl/austin/tree.c b/reactos/lib/rtl/austin/tree.c index 55632a1aa7d..21b5055de92 100644 --- a/reactos/lib/rtl/austin/tree.c +++ b/reactos/lib/rtl/austin/tree.c @@ -30,10 +30,16 @@ void udict_tree_delete(udict_t *ud, udict_node_t *node, udict_node_t **pswap, ud udict_node_t *nil = tree_null_priv(ud), *child, *delparent = node->parent; udict_node_t *next = node, *nextparent; + if( tree_root_priv(ud) == node ) + delparent = &ud->BalancedRoot; + if (node->left != nil && node->right != nil) { next = udict_tree_next(ud, node); nextparent = next->parent; + if( tree_root_priv(ud) == next ) + nextparent = &ud->BalancedRoot; + assert (next != nil); assert (next->parent != nil); assert (next->left == nil); @@ -76,20 +82,19 @@ void udict_tree_delete(udict_t *ud, udict_node_t *node, udict_node_t **pswap, ud assert (node->left == nil || node->right == nil); child = (node->left != nil) ? node->left : node->right; - child->parent = delparent = node->parent; if (node == delparent->left) { delparent->left = child; } else { - //assert (node == delparent->right); + assert (node == delparent->right); delparent->right = child; } } - node->parent = 0; - node->right = 0; - node->left = 0; + node->parent = nil; + node->right = nil; + node->left = nil; ud->nodecount--; diff --git a/reactos/lib/rtl/generictable.c b/reactos/lib/rtl/generictable.c index 0bfb2897240..fff9e5dc15b 100644 --- a/reactos/lib/rtl/generictable.c +++ b/reactos/lib/rtl/generictable.c @@ -132,6 +132,8 @@ RtlDeleteElementGenericTableAvl ( { avl_delete_node(Table, Node); Table->FreeRoutine(Table, Node); + if( Table->NumberGenericTableElements == 0 ) + avl_deinit(Table); return TRUE; } else @@ -303,7 +305,6 @@ RtlInitializeGenericTableAvl(IN OUT PRTL_AVL_TABLE Table, Table->AllocateRoutine = AllocateRoutine; Table->FreeRoutine = FreeRoutine; Table->TableContext = TableContext; - avl_init(Table); } @@ -358,6 +359,10 @@ RtlInsertElementGenericTableFullAvl ( PRTL_BALANCED_LINKS OurNodeOrParent; TABLE_SEARCH_RESULT OurSearchResult; + if(Table->NumberGenericTableElements == 0) { + avl_init(Table); + } + if(NewElement) *NewElement = FALSE;