mirror of
https://github.com/reactos/reactos.git
synced 2024-09-19 17:21:14 +00:00
29fa274d6d
- TSVN choked repeatedly when attempting to merge ~9000 revs into the branch (tried 3 times on 2 different computers) - If someone wants to delete aicom-network-fixes, they are welcome to - Lesson learned: Letting a branch get thousands of revs out of date is a horrible idea svn path=/branches/aicom-network-branch/; revision=44353
293 lines
6.8 KiB
C
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;
|
|
}
|
|
|