diff options
Diffstat (limited to 'aapl/avlcommon.h')
-rw-r--r-- | aapl/avlcommon.h | 1630 |
1 files changed, 1630 insertions, 0 deletions
diff --git a/aapl/avlcommon.h b/aapl/avlcommon.h new file mode 100644 index 0000000..a00455b --- /dev/null +++ b/aapl/avlcommon.h @@ -0,0 +1,1630 @@ +/* + * Copyright 2001 Adrian Thurston <thurston@complang.org> + */ + +/* This file is part of Aapl. + * + * Aapl is free software; you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Aapl; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* This header is not wrapped in ifndef becuase it is not intended to + * be included by the user. */ + +#include <assert.h> + +#ifdef AAPL_NAMESPACE +namespace Aapl { +#endif + +#ifdef WALKABLE +/* This is used by AvlTree, AvlMel and AvlMelKey so it + * must be protected by global ifdefs. */ +#ifndef __AAPL_AVLI_EL__ +#define __AAPL_AVLI_EL__ + +/** + * \brief Tree element properties for linked AVL trees. + * + * AvliTreeEl needs to be inherited by classes that intend to be element in an + * AvliTree. + */ +template<class SubClassEl> struct AvliTreeEl +{ + /** + * \brief Tree pointers connecting element in a tree. + */ + SubClassEl *left, *right, *parent; + + /** + * \brief Linked list pointers. + */ + SubClassEl *prev, *next; + + /** + * \brief Height of the tree rooted at this element. + * + * Height is required by the AVL balancing algorithm. + */ + long height; +}; +#endif /* __AAPL_AVLI_EL__ */ + +#else /* not WALKABLE */ + +/* This is used by All the non walkable trees so it must be + * protected by a global ifdef. */ +#ifndef __AAPL_AVL_EL__ +#define __AAPL_AVL_EL__ +/** + * \brief Tree element properties for linked AVL trees. + * + * AvlTreeEl needs to be inherited by classes that intend to be element in an + * AvlTree. + */ +template<class SubClassEl> struct AvlTreeEl +{ + /** + * \brief Tree pointers connecting element in a tree. + */ + SubClassEl *left, *right, *parent; + + /** + * \brief Height of the tree rooted at this element. + * + * Height is required by the AVL balancing algorithm. + */ + long height; +}; +#endif /* __AAPL_AVL_EL__ */ +#endif /* def WALKABLE */ + + +#if defined( AVLTREE_MAP ) + +#ifdef WALKABLE + +/** + * \brief Tree element for AvliMap + * + * Stores the key and value pair. + */ +template <class Key, class Value> struct AvliMapEl : + public AvliTreeEl< AvliMapEl<Key, Value> > +{ + AvliMapEl(const Key &key) + : key(key) { } + AvliMapEl(const Key &key, const Value &value) + : key(key), value(value) { } + + const Key &getKey() const { return key; } + + /** \brief The key. */ + Key key; + + /** \brief The value. */ + Value value; +}; +#else /* not WALKABLE */ + +/** + * \brief Tree element for AvlMap + * + * Stores the key and value pair. + */ +template <class Key, class Value> struct AvlMapEl : + public AvlTreeEl< AvlMapEl<Key, Value> > +{ + AvlMapEl(const Key &key) + : key(key) { } + AvlMapEl(const Key &key, const Value &value) + : key(key), value(value) { } + + const Key &getKey() const { return key; } + + /** \brief The key. */ + Key key; + + /** \brief The value. */ + Value value; +}; +#endif /* def WALKABLE */ + +#elif defined( AVLTREE_SET ) + +#ifdef WALKABLE +/** + * \brief Tree element for AvliSet + * + * Stores the key. + */ +template <class Key> struct AvliSetEl : + public AvliTreeEl< AvliSetEl<Key> > +{ + AvliSetEl(const Key &key) : key(key) { } + + const Key &getKey() const { return key; } + + /** \brief The key. */ + Key key; +}; +#else /* not WALKABLE */ +/** + * \brief Tree element for AvlSet + * + * Stores the key. + */ +template <class Key> struct AvlSetEl : + public AvlTreeEl< AvlSetEl<Key> > +{ + AvlSetEl(const Key &key) : key(key) { } + + const Key &getKey() const { return key; } + + /** \brief The key. */ + Key key; +}; +#endif /* def WALKABLE */ + +#endif /* AVLTREE_SET */ + +/* Common AvlTree Class */ +template < AVLMEL_CLASSDEF > class AvlTree +#if !defined( AVL_KEYLESS ) && defined ( WALKABLE ) + : public Compare, public BASELIST +#elif !defined( AVL_KEYLESS ) + : public Compare +#elif defined( WALKABLE ) + : public BASELIST +#endif +{ +public: + /** + * \brief Create an empty tree. + */ +#ifdef WALKABLE + AvlTree() : root(0), treeSize(0) { } +#else + AvlTree() : root(0), head(0), tail(0), treeSize(0) { } +#endif + + /** + * \brief Perform a deep copy of the tree. + * + * Each element is duplicated for the new tree. Copy constructors are used + * to create the new elements. + */ + AvlTree(const AvlTree &other); + +#if defined( AVLTREE_MAP ) || defined( AVLTREE_SET ) + /** + * \brief Clear the contents of the tree. + * + * All element are deleted. + */ + ~AvlTree() { empty(); } + + /** + * \brief Perform a deep copy of the tree. + * + * Each element is duplicated for the new tree. Copy constructors are used + * to create the new element. If this tree contains items, they are first + * deleted. + * + * \returns A reference to this. + */ + AvlTree &operator=( const AvlTree &tree ); + + /** + * \brief Transfer the elements of another tree into this. + * + * First deletes all elements in this tree. + */ + void transfer( AvlTree &tree ); +#else + /** + * \brief Abandon all elements in the tree. + * + * Tree elements are not deleted. + */ + ~AvlTree() {} + + /** + * \brief Perform a deep copy of the tree. + * + * Each element is duplicated for the new tree. Copy constructors are used + * to create the new element. If this tree contains items, they are + * abandoned. + * + * \returns A reference to this. + */ + AvlTree &operator=( const AvlTree &tree ); + + /** + * \brief Transfer the elements of another tree into this. + * + * All elements in this tree are abandoned first. + */ + void transfer( AvlTree &tree ); +#endif + +#ifndef AVL_KEYLESS + /* Insert a element into the tree. */ + Element *insert( Element *element, Element **lastFound = 0 ); + +#ifdef AVL_BASIC + /* Find a element in the tree. Returns the element if + * element exists, false otherwise. */ + Element *find( const Element *element ) const; + +#else + Element *insert( const Key &key, Element **lastFound = 0 ); + +#ifdef AVLTREE_MAP + Element *insert( const Key &key, const Value &val, + Element **lastFound = 0 ); +#endif + + /* Find a element in the tree. Returns the element if + * key exists, false otherwise. */ + Element *find( const Key &key ) const; + + /* Detach a element from the tree. */ + Element *detach( const Key &key ); + + /* Detach and delete a element from the tree. */ + bool remove( const Key &key ); +#endif /* AVL_BASIC */ +#endif /* AVL_KEYLESS */ + + /* Detach a element from the tree. */ + Element *detach( Element *element ); + + /* Detach and delete a element from the tree. */ + void remove( Element *element ); + + /* Free all memory used by tree. */ + void empty(); + + /* Abandon all element in the tree. Does not delete element. */ + void abandon(); + + /** Root element of the tree. */ + Element *root; + +#ifndef WALKABLE + Element *head, *tail; +#endif + + /** The number of element in the tree. */ + long treeSize; + + /** \brief Return the number of elements in the tree. */ + long length() const { return treeSize; } + + /** \brief Return the number of elements in the tree. */ + long size() const { return treeSize; } + + /* Various classes for setting the iterator */ + struct Iter; + struct IterFirst { IterFirst( const AvlTree &t ) : t(t) { } const AvlTree &t; }; + struct IterLast { IterLast( const AvlTree &t ) : t(t) { } const AvlTree &t; }; + struct IterNext { IterNext( const Iter &i ) : i(i) { } const Iter &i; }; + struct IterPrev { IterPrev( const Iter &i ) : i(i) { } const Iter &i; }; + +#ifdef WALKABLE + /** + * \brief Avl Tree Iterator. + * \ingroup iterators + */ + struct Iter + { + /* Default construct. */ + Iter() : ptr(0) { } + + /* Construct from an avl tree and iterator-setting classes. */ + Iter( const AvlTree &t ) : ptr(t.head) { } + Iter( const IterFirst &af ) : ptr(af.t.head) { } + Iter( const IterLast &al ) : ptr(al.t.tail) { } + Iter( const IterNext &an ) : ptr(findNext(an.i.ptr)) { } + Iter( const IterPrev &ap ) : ptr(findPrev(ap.i.ptr)) { } + + /* Assign from a tree and iterator-setting classes. */ + Iter &operator=( const AvlTree &tree ) { ptr = tree.head; return *this; } + Iter &operator=( const IterFirst &af ) { ptr = af.t.head; return *this; } + Iter &operator=( const IterLast &al ) { ptr = al.t.tail; return *this; } + Iter &operator=( const IterNext &an ) { ptr = findNext(an.i.ptr); return *this; } + Iter &operator=( const IterPrev &ap ) { ptr = findPrev(ap.i.ptr); return *this; } + + /** \brief Less than end? */ + bool lte() const { return ptr != 0; } + + /** \brief At end? */ + bool end() const { return ptr == 0; } + + /** \brief Greater than beginning? */ + bool gtb() const { return ptr != 0; } + + /** \brief At beginning? */ + bool beg() const { return ptr == 0; } + + /** \brief At first element? */ + bool first() const { return ptr && ptr->BASE_EL(prev) == 0; } + + /** \brief At last element? */ + bool last() const { return ptr && ptr->BASE_EL(next) == 0; } + + /** \brief Implicit cast to Element*. */ + operator Element*() const { return ptr; } + + /** \brief Dereference operator returns Element&. */ + Element &operator *() const { return *ptr; } + + /** \brief Arrow operator returns Element*. */ + Element *operator->() const { return ptr; } + + /** \brief Move to next item. */ + inline Element *operator++(); + + /** \brief Move to next item. */ + inline Element *operator++(int); + + /** \brief Move to next item. */ + inline Element *increment(); + + /** \brief Move to previous item. */ + inline Element *operator--(); + + /** \brief Move to previous item. */ + inline Element *operator--(int); + + /** \brief Move to previous item. */ + inline Element *decrement(); + + /** \brief Return the next item. Does not modify this. */ + IterNext next() const { return IterNext( *this ); } + + /** \brief Return the previous item. Does not modify this. */ + IterPrev prev() const { return IterPrev( *this ); } + + private: + static Element *findPrev( Element *element ) { return element->BASE_EL(prev); } + static Element *findNext( Element *element ) { return element->BASE_EL(next); } + + public: + + /** \brief The iterator is simply a pointer. */ + Element *ptr; + }; + +#else + + /** + * \brief Avl Tree Iterator. + * \ingroup iterators + */ + struct Iter + { + /* Default construct. */ + Iter() : ptr(0), tree(0) { } + + /* Construct from a tree and iterator-setting classes. */ + Iter( const AvlTree &t ) : ptr(t.head), tree(&t) { } + Iter( const IterFirst &af ) : ptr(af.t.head), tree(&af.t) { } + Iter( const IterLast &al ) : ptr(al.t.tail), tree(&al.t) { } + Iter( const IterNext &an ) : ptr(findNext(an.i.ptr)), tree(an.i.tree) { } + Iter( const IterPrev &ap ) : ptr(findPrev(ap.i.ptr)), tree(ap.i.tree) { } + + /* Assign from a tree and iterator-setting classes. */ + Iter &operator=( const AvlTree &t ) + { ptr = t.head; tree = &t; return *this; } + Iter &operator=( const IterFirst &af ) + { ptr = af.t.head; tree = &af.t; return *this; } + Iter &operator=( const IterLast &al ) + { ptr = al.t.tail; tree = &al.t; return *this; } + Iter &operator=( const IterNext &an ) + { ptr = findNext(an.i.ptr); tree = an.i.tree; return *this; } + Iter &operator=( const IterPrev &ap ) + { ptr = findPrev(ap.i.ptr); tree = ap.i.tree; return *this; } + + /** \brief Less than end? */ + bool lte() const { return ptr != 0; } + + /** \brief At end? */ + bool end() const { return ptr == 0; } + + /** \brief Greater than beginning? */ + bool gtb() const { return ptr != 0; } + + /** \brief At beginning? */ + bool beg() const { return ptr == 0; } + + /** \brief At first element? */ + bool first() const { return ptr && ptr == tree->head; } + + /** \brief At last element? */ + bool last() const { return ptr && ptr == tree->tail; } + + /** \brief Implicit cast to Element*. */ + operator Element*() const { return ptr; } + + /** \brief Dereference operator returns Element&. */ + Element &operator *() const { return *ptr; } + + /** \brief Arrow operator returns Element*. */ + Element *operator->() const { return ptr; } + + /** \brief Move to next item. */ + inline Element *operator++(); + + /** \brief Move to next item. */ + inline Element *operator++(int); + + /** \brief Move to next item. */ + inline Element *increment(); + + /** \brief Move to previous item. */ + inline Element *operator--(); + + /** \brief Move to previous item. */ + inline Element *operator--(int); + + /** \brief Move to previous item. */ + inline Element *decrement(); + + /** \brief Return the next item. Does not modify this. */ + IterNext next() const { return IterNext( *this ); } + + /** \brief Return the previous item. Does not modify this. */ + IterPrev prev() const { return IterPrev( *this ); } + + private: + static Element *findPrev( Element *element ); + static Element *findNext( Element *element ); + + public: + /** \brief The iterator is simply a pointer. */ + Element *ptr; + + /* The list is not walkable so we need to keep a pointerto the tree + * so we can test against head and tail in O(1) time. */ + const AvlTree *tree; + }; +#endif + + /** \brief Return first element. */ + IterFirst first() { return IterFirst( *this ); } + + /** \brief Return last element. */ + IterLast last() { return IterLast( *this ); } + +protected: + /* Recursive worker for the copy constructor. */ + Element *copyBranch( Element *element ); + + /* Recursively delete element in the tree. */ + void deleteChildrenOf(Element *n); + + /* rebalance the tree beginning at the leaf whose + * grandparent is unbalanced. */ + Element *rebalance(Element *start); + + /* Move up the tree from a given element, recalculating the heights. */ + void recalcHeights(Element *start); + + /* Move up the tree and find the first element whose + * grand-parent is unbalanced. */ + Element *findFirstUnbalGP(Element *start); + + /* Move up the tree and find the first element which is unbalanced. */ + Element *findFirstUnbalEl(Element *start); + + /* Replace a element in the tree with another element not in the tree. */ + void replaceEl(Element *element, Element *replacement); + + /* Remove a element from the tree and put another (normally a child of element) + * in its place. */ + void removeEl(Element *element, Element *filler); + + /* Once an insertion point is found at a leaf then do the insert. */ + void attachRebal( Element *element, Element *parentEl, Element *lastLess ); +}; + +/* Copy constructor. New up each item. */ +template <AVLMEL_TEMPDEF> AvlTree<AVLMEL_TEMPUSE>:: + AvlTree(const AvlTree<AVLMEL_TEMPUSE> &other) +#if !defined( AVL_KEYLESS ) && defined ( WALKABLE ) + /* BASELIST should be made empty. The copyBranch function + * will fill in the details for us. */ + : Compare( other ), BASELIST() +#elif !defined( AVL_KEYLESS ) + : Compare( other ) +#elif defined( WALKABLE ) + : BASELIST( ) +#endif +{ + treeSize = other.treeSize; + root = other.root; + +#ifndef WALKABLE + head = 0; + tail = 0; +#endif + + /* If there is a root, copy the tree. */ + if ( other.root != 0 ) + root = copyBranch( other.root ); +} + +#if defined( AVLTREE_MAP ) || defined( AVLTREE_SET ) + +/* Assignment does deep copy. */ +template <AVLMEL_TEMPDEF> AvlTree<AVLMEL_TEMPUSE> &AvlTree<AVLMEL_TEMPUSE>:: + operator=( const AvlTree &other ) +{ + /* Clear the tree first. */ + empty(); + + /* Reset the list pointers, the tree copy will fill in the list for us. */ +#ifdef WALKABLE + BASELIST::abandon(); +#else + head = 0; + tail = 0; +#endif + + /* Copy the entire tree. */ + treeSize = other.treeSize; + root = other.root; + if ( other.root != 0 ) + root = copyBranch( other.root ); + return *this; +} + +template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>:: + transfer(AvlTree<AVLMEL_TEMPUSE> &other) +{ + /* Clear the tree first. */ + empty(); + + treeSize = other.treeSize; + root = other.root; + +#ifdef WALKABLE + BASELIST::head = other.BASELIST::head; + BASELIST::tail = other.BASELIST::tail; + BASELIST::listLen = other.BASELIST::listLen; +#else + head = other.head; + tail = other.tail; +#endif + + other.abandon(); +} + +#else /* ! AVLTREE_MAP && ! AVLTREE_SET */ + +/* Assignment does deep copy. This version does not clear the tree first. */ +template <AVLMEL_TEMPDEF> AvlTree<AVLMEL_TEMPUSE> &AvlTree<AVLMEL_TEMPUSE>:: + operator=( const AvlTree &other ) +{ + /* Reset the list pointers, the tree copy will fill in the list for us. */ +#ifdef WALKABLE + BASELIST::abandon(); +#else + head = 0; + tail = 0; +#endif + + /* Copy the entire tree. */ + treeSize = other.treeSize; + root = other.root; + if ( other.root != 0 ) + root = copyBranch( other.root ); + return *this; +} + +template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>:: + transfer(AvlTree<AVLMEL_TEMPUSE> &other) +{ + treeSize = other.treeSize; + root = other.root; + +#ifdef WALKABLE + BASELIST::head = other.BASELIST::head; + BASELIST::tail = other.BASELIST::tail; + BASELIST::listLen = other.BASELIST::listLen; +#else + head = other.head; + tail = other.tail; +#endif + + other.abandon(); +} + +#endif + +/* + * Iterator operators. + */ + +/* Prefix ++ */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter:: + operator++() +{ + return ptr = findNext( ptr ); +} + +/* Postfix ++ */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter:: + operator++(int) +{ + Element *rtn = ptr; + ptr = findNext( ptr ); + return rtn; +} + +/* increment */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter:: + increment() +{ + return ptr = findNext( ptr ); +} + +/* Prefix -- */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter:: + operator--() +{ + return ptr = findPrev( ptr ); +} + +/* Postfix -- */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter:: + operator--(int) +{ + Element *rtn = ptr; + ptr = findPrev( ptr ); + return rtn; +} + +/* decrement */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter:: + decrement() +{ + return ptr = findPrev( ptr ); +} + +#ifndef WALKABLE + +/* Move ahead one. */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter:: + findNext( Element *element ) +{ + /* Try to go right once then infinite left. */ + if ( element->BASE_EL(right) != 0 ) { + element = element->BASE_EL(right); + while ( element->BASE_EL(left) != 0 ) + element = element->BASE_EL(left); + } + else { + /* Go up to parent until we were just a left child. */ + while ( true ) { + Element *last = element; + element = element->BASE_EL(parent); + if ( element == 0 || element->BASE_EL(left) == last ) + break; + } + } + return element; +} + +/* Move back one. */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>::Iter:: + findPrev( Element *element ) +{ + /* Try to go left once then infinite right. */ + if ( element->BASE_EL(left) != 0 ) { + element = element->BASE_EL(left); + while ( element->BASE_EL(right) != 0 ) + element = element->BASE_EL(right); + } + else { + /* Go up to parent until we were just a left child. */ + while ( true ) { + Element *last = element; + element = element->BASE_EL(parent); + if ( element == 0 || element->BASE_EL(right) == last ) + break; + } + } + return element; +} + +#endif + + +/* Recursive worker for tree copying. */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>:: + copyBranch( Element *element ) +{ + /* Duplicate element. Either the base element's copy constructor or defaul + * constructor will get called. Both will suffice for initting the + * pointers to null when they need to be. */ + Element *retVal = new Element(*element); + + /* If the left tree is there, copy it. */ + if ( retVal->BASE_EL(left) ) { + retVal->BASE_EL(left) = copyBranch(retVal->BASE_EL(left)); + retVal->BASE_EL(left)->BASE_EL(parent) = retVal; + } + +#ifdef WALKABLE + BASELIST::addAfter( BASELIST::tail, retVal ); +#else + if ( head == 0 ) + head = retVal; + tail = retVal; +#endif + + /* If the right tree is there, copy it. */ + if ( retVal->BASE_EL(right) ) { + retVal->BASE_EL(right) = copyBranch(retVal->BASE_EL(right)); + retVal->BASE_EL(right)->BASE_EL(parent) = retVal; + } + return retVal; +} + +/* Once an insertion position is found, attach a element to the tree. */ +template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>:: + attachRebal( Element *element, Element *parentEl, Element *lastLess ) +{ + /* Increment the number of element in the tree. */ + treeSize += 1; + + /* Set element's parent. */ + element->BASE_EL(parent) = parentEl; + + /* New element always starts as a leaf with height 1. */ + element->BASE_EL(left) = 0; + element->BASE_EL(right) = 0; + element->BASE_EL(height) = 1; + + /* Are we inserting in the tree somewhere? */ + if ( parentEl != 0 ) { + /* We have a parent so we are somewhere in the tree. If the parent + * equals lastLess, then the last traversal in the insertion went + * left, otherwise it went right. */ + if ( lastLess == parentEl ) { + parentEl->BASE_EL(left) = element; +#ifdef WALKABLE + BASELIST::addBefore( parentEl, element ); +#endif + } + else { + parentEl->BASE_EL(right) = element; +#ifdef WALKABLE + BASELIST::addAfter( parentEl, element ); +#endif + } + +#ifndef WALKABLE + /* Maintain the first and last pointers. */ + if ( head->BASE_EL(left) == element ) + head = element; + + /* Maintain the first and last pointers. */ + if ( tail->BASE_EL(right) == element ) + tail = element; +#endif + } + else { + /* No parent element so we are inserting the root. */ + root = element; +#ifdef WALKABLE + BASELIST::addAfter( BASELIST::tail, element ); +#else + head = tail = element; +#endif + } + + + /* Recalculate the heights. */ + recalcHeights(parentEl); + + /* Find the first unbalance. */ + Element *ub = findFirstUnbalGP(element); + + /* rebalance. */ + if ( ub != 0 ) + { + /* We assert that after this single rotation the + * tree is now properly balanced. */ + rebalance(ub); + } +} + +#ifndef AVL_KEYLESS + +/** + * \brief Insert an existing element into the tree. + * + * If the insert succeeds and lastFound is given then it is set to the element + * inserted. If the insert fails then lastFound is set to the existing element in + * the tree that has the same key as element. If the element's avl pointers are + * already in use then undefined behaviour results. + * + * \returns The element inserted upon success, null upon failure. + */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>:: + insert( Element *element, Element **lastFound ) +{ + long keyRelation; + Element *curEl = root, *parentEl = 0; + Element *lastLess = 0; + + while (true) { + if ( curEl == 0 ) { + /* We are at an external element and did not find the key we were + * looking for. Attach underneath the leaf and rebalance. */ + attachRebal( element, parentEl, lastLess ); + + if ( lastFound != 0 ) + *lastFound = element; + return element; + } + +#ifdef AVL_BASIC + keyRelation = this->compare( *element, *curEl ); +#else + keyRelation = this->compare( element->BASEKEY(getKey()), + curEl->BASEKEY(getKey()) ); +#endif + + /* Do we go left? */ + if ( keyRelation < 0 ) { + parentEl = lastLess = curEl; + curEl = curEl->BASE_EL(left); + } + /* Do we go right? */ + else if ( keyRelation > 0 ) { + parentEl = curEl; + curEl = curEl->BASE_EL(right); + } + /* We have hit the target. */ + else { + if ( lastFound != 0 ) + *lastFound = curEl; + return 0; + } + } +} + +#ifdef AVL_BASIC + +/** + * \brief Find a element in the tree with the given key. + * + * \returns The element if key exists, null if the key does not exist. + */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>:: + find( const Element *element ) const +{ + Element *curEl = root; + long keyRelation; + + while (curEl) { + keyRelation = this->compare( *element, *curEl ); + + /* Do we go left? */ + if ( keyRelation < 0 ) + curEl = curEl->BASE_EL(left); + /* Do we go right? */ + else if ( keyRelation > 0 ) + curEl = curEl->BASE_EL(right); + /* We have hit the target. */ + else { + return curEl; + } + } + return 0; +} + +#else + +/** + * \brief Insert a new element into the tree with given key. + * + * If the key is not already in the tree then a new element is made using the + * Element(const Key &key) constructor and the insert succeeds. If lastFound is + * given then it is set to the element inserted. If the insert fails then + * lastFound is set to the existing element in the tree that has the same key as + * element. + * + * \returns The new element upon success, null upon failure. + */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>:: + insert( const Key &key, Element **lastFound ) +{ + long keyRelation; + Element *curEl = root, *parentEl = 0; + Element *lastLess = 0; + + while (true) { + if ( curEl == 0 ) { + /* We are at an external element and did not find the key we were + * looking for. Create the new element, attach it underneath the leaf + * and rebalance. */ + Element *element = new Element( key ); + attachRebal( element, parentEl, lastLess ); + + if ( lastFound != 0 ) + *lastFound = element; + return element; + } + + keyRelation = this->compare( key, curEl->BASEKEY(getKey()) ); + + /* Do we go left? */ + if ( keyRelation < 0 ) { + parentEl = lastLess = curEl; + curEl = curEl->BASE_EL(left); + } + /* Do we go right? */ + else if ( keyRelation > 0 ) { + parentEl = curEl; + curEl = curEl->BASE_EL(right); + } + /* We have hit the target. */ + else { + if ( lastFound != 0 ) + *lastFound = curEl; + return 0; + } + } +} + +#ifdef AVLTREE_MAP +/** + * \brief Insert a new element into the tree with key and value. + * + * If the key is not already in the tree then a new element is constructed and + * the insert succeeds. If lastFound is given then it is set to the element + * inserted. If the insert fails then lastFound is set to the existing element in + * the tree that has the same key as element. This insert routine is only + * available in AvlMap because it is the only class that knows about a Value + * type. + * + * \returns The new element upon success, null upon failure. + */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>:: + insert( const Key &key, const Value &val, Element **lastFound ) +{ + long keyRelation; + Element *curEl = root, *parentEl = 0; + Element *lastLess = 0; + + while (true) { + if ( curEl == 0 ) { + /* We are at an external element and did not find the key we were + * looking for. Create the new element, attach it underneath the leaf + * and rebalance. */ + Element *element = new Element( key, val ); + attachRebal( element, parentEl, lastLess ); + + if ( lastFound != 0 ) + *lastFound = element; + return element; + } + + keyRelation = this->compare(key, curEl->getKey()); + + /* Do we go left? */ + if ( keyRelation < 0 ) { + parentEl = lastLess = curEl; + curEl = curEl->BASE_EL(left); + } + /* Do we go right? */ + else if ( keyRelation > 0 ) { + parentEl = curEl; + curEl = curEl->BASE_EL(right); + } + /* We have hit the target. */ + else { + if ( lastFound != 0 ) + *lastFound = curEl; + return 0; + } + } +} +#endif /* AVLTREE_MAP */ + + +/** + * \brief Find a element in the tree with the given key. + * + * \returns The element if key exists, null if the key does not exist. + */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>:: + find( const Key &key ) const +{ + Element *curEl = root; + long keyRelation; + + while (curEl) { + keyRelation = this->compare( key, curEl->BASEKEY(getKey()) ); + + /* Do we go left? */ + if ( keyRelation < 0 ) + curEl = curEl->BASE_EL(left); + /* Do we go right? */ + else if ( keyRelation > 0 ) + curEl = curEl->BASE_EL(right); + /* We have hit the target. */ + else { + return curEl; + } + } + return 0; +} + + +/** + * \brief Find a element, then detach it from the tree. + * + * The element is not deleted. + * + * \returns The element detached if the key is found, othewise returns null. + */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>:: + detach(const Key &key) +{ + Element *element = find( key ); + if ( element ) { + detach(element); + } + + return element; +} + +/** + * \brief Find, detach and delete a element from the tree. + * + * \returns True if the element was found and deleted, false otherwise. + */ +template <AVLMEL_TEMPDEF> bool AvlTree<AVLMEL_TEMPUSE>:: + remove(const Key &key) +{ + /* Assume not found. */ + bool retVal = false; + + /* Look for the key. */ + Element *element = find( key ); + if ( element != 0 ) { + /* If found, detach the element and delete. */ + detach( element ); + delete element; + retVal = true; + } + + return retVal; +} + +#endif /* AVL_BASIC */ +#endif /* AVL_KEYLESS */ + + +/** + * \brief Detach and delete a element from the tree. + * + * If the element is not in the tree then undefined behaviour results. + */ +template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>:: + remove(Element *element) +{ + /* Detach and delete. */ + detach(element); + delete element; +} + +/** + * \brief Detach a element from the tree. + * + * If the element is not in the tree then undefined behaviour results. + * + * \returns The element given. + */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>:: + detach(Element *element) +{ + Element *replacement, *fixfrom; + long lheight, rheight; + +#ifdef WALKABLE + /* Remove the element from the ordered list. */ + BASELIST::detach( element ); +#endif + + /* Update treeSize. */ + treeSize--; + + /* Find a replacement element. */ + if (element->BASE_EL(right)) + { + /* Find the leftmost element of the right subtree. */ + replacement = element->BASE_EL(right); + while (replacement->BASE_EL(left)) + replacement = replacement->BASE_EL(left); + + /* If replacing the element the with its child then we need to start + * fixing at the replacement, otherwise we start fixing at the + * parent of the replacement. */ + if (replacement->BASE_EL(parent) == element) + fixfrom = replacement; + else + fixfrom = replacement->BASE_EL(parent); + +#ifndef WALKABLE + if ( element == head ) + head = replacement; +#endif + + removeEl(replacement, replacement->BASE_EL(right)); + replaceEl(element, replacement); + } + else if (element->BASE_EL(left)) + { + /* Find the rightmost element of the left subtree. */ + replacement = element->BASE_EL(left); + while (replacement->BASE_EL(right)) + replacement = replacement->BASE_EL(right); + + /* If replacing the element the with its child then we need to start + * fixing at the replacement, otherwise we start fixing at the + * parent of the replacement. */ + if (replacement->BASE_EL(parent) == element) + fixfrom = replacement; + else + fixfrom = replacement->BASE_EL(parent); + +#ifndef WALKABLE + if ( element == tail ) + tail = replacement; +#endif + + removeEl(replacement, replacement->BASE_EL(left)); + replaceEl(element, replacement); + } + else + { + /* We need to start fixing at the parent of the element. */ + fixfrom = element->BASE_EL(parent); + +#ifndef WALKABLE + if ( element == head ) + head = element->BASE_EL(parent); + if ( element == tail ) + tail = element->BASE_EL(parent); +#endif + + /* The element we are deleting is a leaf element. */ + removeEl(element, 0); + } + + /* If fixfrom is null it means we just deleted + * the root of the tree. */ + if ( fixfrom == 0 ) + return element; + + /* Fix the heights after the deletion. */ + recalcHeights(fixfrom); + + /* Fix every unbalanced element going up in the tree. */ + Element *ub = findFirstUnbalEl(fixfrom); + while ( ub ) + { + /* Find the element to rebalance by moving down from the first unbalanced + * element 2 levels in the direction of the greatest heights. On the + * second move down, the heights may be equal ( but not on the first ). + * In which case go in the direction of the first move. */ + lheight = ub->BASE_EL(left) ? ub->BASE_EL(left)->BASE_EL(height) : 0; + rheight = ub->BASE_EL(right) ? ub->BASE_EL(right)->BASE_EL(height) : 0; + assert( lheight != rheight ); + if (rheight > lheight) + { + ub = ub->BASE_EL(right); + lheight = ub->BASE_EL(left) ? + ub->BASE_EL(left)->BASE_EL(height) : 0; + rheight = ub->BASE_EL(right) ? + ub->BASE_EL(right)->BASE_EL(height) : 0; + if (rheight > lheight) + ub = ub->BASE_EL(right); + else if (rheight < lheight) + ub = ub->BASE_EL(left); + else + ub = ub->BASE_EL(right); + } + else + { + ub = ub->BASE_EL(left); + lheight = ub->BASE_EL(left) ? + ub->BASE_EL(left)->BASE_EL(height) : 0; + rheight = ub->BASE_EL(right) ? + ub->BASE_EL(right)->BASE_EL(height) : 0; + if (rheight > lheight) + ub = ub->BASE_EL(right); + else if (rheight < lheight) + ub = ub->BASE_EL(left); + else + ub = ub->BASE_EL(left); + } + + + /* rebalance returns the grandparant of the subtree formed + * by the element that were rebalanced. + * We must continue upward from there rebalancing. */ + fixfrom = rebalance(ub); + + /* Find the next unbalaced element. */ + ub = findFirstUnbalEl(fixfrom); + } + + return element; +} + + +/** + * \brief Empty the tree and delete all the element. + * + * Resets the tree to its initial state. + */ +template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::empty() +{ + if ( root ) { + /* Recursively delete from the tree structure. */ + deleteChildrenOf(root); + delete root; + root = 0; + treeSize = 0; + +#ifdef WALKABLE + BASELIST::abandon(); +#endif + } +} + +/** + * \brief Forget all element in the tree. + * + * Does not delete element. Resets the the tree to it's initial state. + */ +template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>::abandon() +{ + root = 0; + treeSize = 0; + +#ifdef WALKABLE + BASELIST::abandon(); +#endif +} + +/* Recursively delete all the children of a element. */ +template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>:: + deleteChildrenOf( Element *element ) +{ + /* Recurse left. */ + if (element->BASE_EL(left)) { + deleteChildrenOf(element->BASE_EL(left)); + + /* Delete left element. */ + delete element->BASE_EL(left); + element->BASE_EL(left) = 0; + } + + /* Recurse right. */ + if (element->BASE_EL(right)) { + deleteChildrenOf(element->BASE_EL(right)); + + /* Delete right element. */ + delete element->BASE_EL(right); + element->BASE_EL(left) = 0; + } +} + +/* rebalance from a element whose gradparent is unbalanced. Only + * call on a element that has a grandparent. */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>:: + rebalance(Element *n) +{ + long lheight, rheight; + Element *a, *b, *c; + Element *t1, *t2, *t3, *t4; + + Element *p = n->BASE_EL(parent); /* parent (Non-NUL). L*/ + Element *gp = p->BASE_EL(parent); /* Grand-parent (Non-NULL). */ + Element *ggp = gp->BASE_EL(parent); /* Great grand-parent (may be NULL). */ + + if (gp->BASE_EL(right) == p) + { + /* gp + * \ + * p + */ + if (p->BASE_EL(right) == n) + { + /* gp + * \ + * p + * \ + * n + */ + a = gp; + b = p; + c = n; + t1 = gp->BASE_EL(left); + t2 = p->BASE_EL(left); + t3 = n->BASE_EL(left); + t4 = n->BASE_EL(right); + } + else + { + /* gp + * \ + * p + * / + * n + */ + a = gp; + b = n; + c = p; + t1 = gp->BASE_EL(left); + t2 = n->BASE_EL(left); + t3 = n->BASE_EL(right); + t4 = p->BASE_EL(right); + } + } + else + { + /* gp + * / + * p + */ + if (p->BASE_EL(right) == n) + { + /* gp + * / + * p + * \ + * n + */ + a = p; + b = n; + c = gp; + t1 = p->BASE_EL(left); + t2 = n->BASE_EL(left); + t3 = n->BASE_EL(right); + t4 = gp->BASE_EL(right); + } + else + { + /* gp + * / + * p + * / + * n + */ + a = n; + b = p; + c = gp; + t1 = n->BASE_EL(left); + t2 = n->BASE_EL(right); + t3 = p->BASE_EL(right); + t4 = gp->BASE_EL(right); + } + } + + /* Perform rotation. + */ + + /* Tie b to the great grandparent. */ + if ( ggp == 0 ) + root = b; + else if ( ggp->BASE_EL(left) == gp ) + ggp->BASE_EL(left) = b; + else + ggp->BASE_EL(right) = b; + b->BASE_EL(parent) = ggp; + + /* Tie a as a leftchild of b. */ + b->BASE_EL(left) = a; + a->BASE_EL(parent) = b; + + /* Tie c as a rightchild of b. */ + b->BASE_EL(right) = c; + c->BASE_EL(parent) = b; + + /* Tie t1 as a leftchild of a. */ + a->BASE_EL(left) = t1; + if ( t1 != 0 ) t1->BASE_EL(parent) = a; + + /* Tie t2 as a rightchild of a. */ + a->BASE_EL(right) = t2; + if ( t2 != 0 ) t2->BASE_EL(parent) = a; + + /* Tie t3 as a leftchild of c. */ + c->BASE_EL(left) = t3; + if ( t3 != 0 ) t3->BASE_EL(parent) = c; + + /* Tie t4 as a rightchild of c. */ + c->BASE_EL(right) = t4; + if ( t4 != 0 ) t4->BASE_EL(parent) = c; + + /* The heights are all recalculated manualy and the great + * grand-parent is passed to recalcHeights() to ensure + * the heights are correct up the tree. + * + * Note that recalcHeights() cuts out when it comes across + * a height that hasn't changed. + */ + + /* Fix height of a. */ + lheight = a->BASE_EL(left) ? a->BASE_EL(left)->BASE_EL(height) : 0; + rheight = a->BASE_EL(right) ? a->BASE_EL(right)->BASE_EL(height) : 0; + a->BASE_EL(height) = (lheight > rheight ? lheight : rheight) + 1; + + /* Fix height of c. */ + lheight = c->BASE_EL(left) ? c->BASE_EL(left)->BASE_EL(height) : 0; + rheight = c->BASE_EL(right) ? c->BASE_EL(right)->BASE_EL(height) : 0; + c->BASE_EL(height) = (lheight > rheight ? lheight : rheight) + 1; + + /* Fix height of b. */ + lheight = a->BASE_EL(height); + rheight = c->BASE_EL(height); + b->BASE_EL(height) = (lheight > rheight ? lheight : rheight) + 1; + + /* Fix height of b's parents. */ + recalcHeights(ggp); + return ggp; +} + +/* Recalculates the heights of all the ancestors of element. */ +template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>:: + recalcHeights(Element *element) +{ + long lheight, rheight, new_height; + while ( element != 0 ) + { + lheight = element->BASE_EL(left) ? element->BASE_EL(left)->BASE_EL(height) : 0; + rheight = element->BASE_EL(right) ? element->BASE_EL(right)->BASE_EL(height) : 0; + + new_height = (lheight > rheight ? lheight : rheight) + 1; + + /* If there is no chage in the height, then there will be no + * change in any of the ancestor's height. We can stop going up. + * If there was a change, continue upward. */ + if (new_height == element->BASE_EL(height)) + return; + else + element->BASE_EL(height) = new_height; + + element = element->BASE_EL(parent); + } +} + +/* Finds the first element whose grandparent is unbalanced. */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>:: + findFirstUnbalGP(Element *element) +{ + long lheight, rheight, balanceProp; + Element *gp; + + if ( element == 0 || element->BASE_EL(parent) == 0 || + element->BASE_EL(parent)->BASE_EL(parent) == 0 ) + return 0; + + /* Don't do anything if we we have no grandparent. */ + gp = element->BASE_EL(parent)->BASE_EL(parent); + while ( gp != 0 ) + { + lheight = gp->BASE_EL(left) ? gp->BASE_EL(left)->BASE_EL(height) : 0; + rheight = gp->BASE_EL(right) ? gp->BASE_EL(right)->BASE_EL(height) : 0; + balanceProp = lheight - rheight; + + if ( balanceProp < -1 || balanceProp > 1 ) + return element; + + element = element->BASE_EL(parent); + gp = gp->BASE_EL(parent); + } + return 0; +} + + +/* Finds the first element that is unbalanced. */ +template <AVLMEL_TEMPDEF> Element *AvlTree<AVLMEL_TEMPUSE>:: + findFirstUnbalEl(Element *element) +{ + if ( element == 0 ) + return 0; + + while ( element != 0 ) + { + long lheight = element->BASE_EL(left) ? + element->BASE_EL(left)->BASE_EL(height) : 0; + long rheight = element->BASE_EL(right) ? + element->BASE_EL(right)->BASE_EL(height) : 0; + long balanceProp = lheight - rheight; + + if ( balanceProp < -1 || balanceProp > 1 ) + return element; + + element = element->BASE_EL(parent); + } + return 0; +} + +/* Replace a element in the tree with another element not in the tree. */ +template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>:: + replaceEl(Element *element, Element *replacement) +{ + Element *parent = element->BASE_EL(parent), + *left = element->BASE_EL(left), + *right = element->BASE_EL(right); + + replacement->BASE_EL(left) = left; + if (left) + left->BASE_EL(parent) = replacement; + replacement->BASE_EL(right) = right; + if (right) + right->BASE_EL(parent) = replacement; + + replacement->BASE_EL(parent) = parent; + if (parent) + { + if (parent->BASE_EL(left) == element) + parent->BASE_EL(left) = replacement; + else + parent->BASE_EL(right) = replacement; + } + else + root = replacement; + + replacement->BASE_EL(height) = element->BASE_EL(height); +} + +/* Removes a element from a tree and puts filler in it's place. + * Filler should be null or a child of element. */ +template <AVLMEL_TEMPDEF> void AvlTree<AVLMEL_TEMPUSE>:: + removeEl(Element *element, Element *filler) +{ + Element *parent = element->BASE_EL(parent); + + if (parent) + { + if (parent->BASE_EL(left) == element) + parent->BASE_EL(left) = filler; + else + parent->BASE_EL(right) = filler; + } + else + root = filler; + + if (filler) + filler->BASE_EL(parent) = parent; + + return; +} + +#ifdef AAPL_NAMESPACE +} +#endif |