/* * Austin---Astonishing Universal Search Tree Interface Novelty * Copyright (C) 2000 Kaz Kylheku * * 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; }