diff options
Diffstat (limited to 'contrib/binutils/libiberty/splay-tree.c')
-rw-r--r-- | contrib/binutils/libiberty/splay-tree.c | 115 |
1 files changed, 112 insertions, 3 deletions
diff --git a/contrib/binutils/libiberty/splay-tree.c b/contrib/binutils/libiberty/splay-tree.c index 22ea07d..52b57c0 100644 --- a/contrib/binutils/libiberty/splay-tree.c +++ b/contrib/binutils/libiberty/splay-tree.c @@ -1,5 +1,5 @@ /* A splay-tree datatype. - Copyright (C) 1998, 1999 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. Contributed by Mark Mitchell (mark@markmitchell.com). This file is part of GNU CC. @@ -32,6 +32,8 @@ Boston, MA 02111-1307, USA. */ #include <stdlib.h> #endif +#include <stdio.h> + #include "libiberty.h" #include "splay-tree.h" @@ -303,12 +305,53 @@ splay_tree_insert (sp, key, value) node->right->left = 0; } - sp->root = node; - } + sp->root = node; + } return sp->root; } +/* Remove KEY from SP. It is not an error if it did not exist. */ + +void +splay_tree_remove (sp, key) + splay_tree sp; + splay_tree_key key; +{ + splay_tree_splay (sp, key); + + if (sp->root && (*sp->comp) (sp->root->key, key) == 0) + { + splay_tree_node left, right; + + left = sp->root->left; + right = sp->root->right; + + /* Delete the root node itself. */ + if (sp->delete_value) + (*sp->delete_value) (sp->root->value); + free (sp->root); + + /* One of the children is now the root. Doesn't matter much + which, so long as we preserve the properties of the tree. */ + if (left) + { + sp->root = left; + + /* If there was a right child as well, hang it off the + right-most leaf of the left child. */ + if (right) + { + while (left->right) + left = left->right; + left->right = right; + } + } + else + sp->root = right; + } +} + /* Lookup KEY in SP, returning VALUE if present, and NULL otherwise. */ @@ -325,6 +368,72 @@ splay_tree_lookup (sp, key) return 0; } +/* Return the immediate predecessor KEY, or NULL if there is no + predecessor. KEY need not be present in the tree. */ + +splay_tree_node +splay_tree_predecessor (sp, key) + splay_tree sp; + splay_tree_key key; +{ + int comparison; + splay_tree_node node; + + /* If the tree is empty, there is certainly no predecessor. */ + if (!sp->root) + return NULL; + + /* Splay the tree around KEY. That will leave either the KEY + itself, its predecessor, or its successor at the root. */ + splay_tree_splay (sp, key); + comparison = (*sp->comp)(sp->root->key, key); + + /* If the predecessor is at the root, just return it. */ + if (comparison < 0) + return sp->root; + + /* Otherwise, find the leftmost element of the right subtree. */ + node = sp->root->left; + if (node) + while (node->right) + node = node->right; + + return node; +} + +/* Return the immediate successor KEY, or NULL if there is no + predecessor. KEY need not be present in the tree. */ + +splay_tree_node +splay_tree_successor (sp, key) + splay_tree sp; + splay_tree_key key; +{ + int comparison; + splay_tree_node node; + + /* If the tree is empty, there is certainly no predecessor. */ + if (!sp->root) + return NULL; + + /* Splay the tree around KEY. That will leave either the KEY + itself, its predecessor, or its successor at the root. */ + splay_tree_splay (sp, key); + comparison = (*sp->comp)(sp->root->key, key); + + /* If the successor is at the root, just return it. */ + if (comparison > 0) + return sp->root; + + /* Otherwise, find the rightmost element of the left subtree. */ + node = sp->root->right; + if (node) + while (node->left) + node = node->left; + + return node; +} + /* Call FN, passing it the DATA, for every node in SP, following an in-order traversal. If FN every returns a non-zero value, the iteration ceases immediately, and the value is returned. |