reactos/lib/rtl/austin/tree.c
Timo Kreuzer 9ea495ba33 Create a branch for header work.
svn path=/branches/header-work/; revision=45691
2010-02-26 22:57:55 +00:00

293 lines
6.8 KiB
C

/*
* Austin---Astonishing Universal Search Tree Interface Novelty
* Copyright (C) 2000 Kaz Kylheku <kaz@ashi.footprints.net>
*
* Free Software License:
*
* All rights are reserved by the author, with the following exceptions:
* Permission is granted to freely reproduce and distribute this software,
* possibly in exchange for a fee, provided that this copyright notice appears
* intact. Permission is also granted to adapt this software to produce
* derivative works, as long as the modified versions carry this copyright
* notice and additional notices stating that the work has been modified.
* This source code may be translated into executable form and incorporated
* into proprietary software; there is no requirement for such software to
* contain a copyright notice related to this source.
*
* $Id: tree.c,v 1.8 1999/12/09 05:38:52 kaz Exp $
* $Name: austin_0_2 $
*/
/*
* Modified for use in ReactOS by arty
*/
#include "rtl.h"
#include "udict.h"
#include "tree.h"
#include "macros.h"
void udict_tree_delete(udict_t *ud, udict_node_t *node, udict_node_t **pswap, udict_node_t **pchild)
{
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);
/*
* First, splice out the successor from the tree completely, by
* moving up its right child into its place.
*/
child = next->right;
child->parent = nextparent;
if (nextparent->left == next) {
nextparent->left = child;
} else {
assert (nextparent->right == next);
nextparent->right = child;
}
/*
* Now that the successor has been extricated from the tree, install it
* in place of the node that we want deleted.
*/
next->parent = delparent;
next->left = node->left;
next->right = node->right;
next->left->parent = next;
next->right->parent = next;
if (delparent->left == node) {
delparent->left = next;
} else {
assert (delparent->right == node);
delparent->right = next;
}
} else {
assert (node != nil);
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);
delparent->right = child;
}
}
node->parent = nil;
node->right = nil;
node->left = nil;
ud->nodecount--;
*pswap = next;
*pchild = child;
}
udict_node_t *udict_tree_lookup(udict_t *ud, const void *_key)
{
udict_node_t *root = tree_root_priv(ud);
udict_node_t *nil = tree_null_priv(ud);
int result;
/* simple binary search adapted for trees that contain duplicate keys */
while (root != nil) {
result = ud->compare(ud, (void *)_key, key(root));
if (result < 0)
root = root->left;
else if (result > 0)
root = root->right;
else {
return root;
}
}
return 0;
}
udict_node_t *udict_tree_lower_bound(udict_t *ud, const void *_key)
{
udict_node_t *root = tree_root_priv(ud);
udict_node_t *nil = tree_null_priv(ud);
udict_node_t *tentative = 0;
while (root != nil) {
int result = ud->compare(ud, (void *)_key, key(root));
if (result > 0) {
root = root->right;
} else if (result < 0) {
tentative = root;
root = root->left;
} else {
return root;
}
}
return tentative;
}
udict_node_t *udict_tree_upper_bound(udict_t *ud, const void *_key)
{
udict_node_t *root = tree_root_priv(ud);
udict_node_t *nil = tree_null_priv(ud);
udict_node_t *tentative = 0;
while (root != nil) {
int result = ud->compare(ud, (void *)_key, key(root));
if (result < 0) {
root = root->left;
} else if (result > 0) {
tentative = root;
root = root->right;
} else {
return root;
}
}
return tentative;
}
udict_node_t *udict_tree_first(udict_t *ud)
{
udict_node_t *nil = tree_null_priv(ud), *root = tree_root_priv(ud), *left;
if (root != nil)
while ((left = root->left) != nil)
root = left;
return (root == nil) ? 0 : root;
}
udict_node_t *udict_tree_last(udict_t *ud)
{
udict_node_t *nil = tree_null_priv(ud), *root = tree_root_priv(ud), *right;
if (root != nil)
while ((right = root->right) != nil)
root = right;
return (root == nil) ? 0 : root;
}
udict_node_t *udict_tree_next(udict_t *ud, udict_node_t *curr)
{
udict_node_t *nil = tree_null_priv(ud), *parent, *left;
if (curr->right != nil) {
curr = curr->right;
while ((left = curr->left) != nil)
curr = left;
return curr;
}
parent = curr->parent;
while (parent != nil && curr == parent->right) {
curr = parent;
parent = curr->parent;
}
return (parent == nil) ? 0 : parent;
}
udict_node_t *udict_tree_prev(udict_t *ud, udict_node_t *curr)
{
udict_node_t *nil = tree_null_priv(ud), *parent, *right;
if (curr->left != nil) {
curr = curr->left;
while ((right = curr->right) != nil)
curr = right;
return curr;
}
parent = curr->parent;
while (parent != nil && curr == parent->left) {
curr = parent;
parent = curr->parent;
}
return (parent == nil) ? 0 : parent;
}
/*
* Perform a ``left rotation'' adjustment on the tree. The given parent node P
* and its right child C are rearranged so that the P instead becomes the left
* child of C. The left subtree of C is inherited as the new right subtree
* for P. The ordering of the keys within the tree is thus preserved.
*/
void udict_tree_rotate_left(udict_node_t *child, udict_node_t *parent)
{
udict_node_t *leftgrandchild, *grandpa;
assert (parent->right == child);
child = parent->right;
parent->right = leftgrandchild = child->left;
leftgrandchild->parent = parent;
child->parent = grandpa = parent->parent;
if (parent == grandpa->left) {
grandpa->left = child;
} else {
assert (parent == grandpa->right);
grandpa->right = child;
}
child->left = parent;
parent->parent = child;
}
/*
* This operation is the ``mirror'' image of rotate_left. It is
* the same procedure, but with left and right interchanged.
*/
void udict_tree_rotate_right(udict_node_t *child, udict_node_t *parent)
{
udict_node_t *rightgrandchild, *grandpa;
assert (parent->left == child);
parent->left = rightgrandchild = child->right;
rightgrandchild->parent = parent;
child->parent = grandpa = parent->parent;
if (parent == grandpa->right) {
grandpa->right = child;
} else {
assert (parent == grandpa->left);
grandpa->left = child;
}
child->right = parent;
parent->parent = child;
}