|
|
/*++
Copyright (c) 1993-1999 Microsoft Corporation
Module Name:
avl.h
Abstract:
AVL tree template class implementation
Author:
Bill Bolosky [bolosky] 1993
Revision History:
--*/
enum AVLBalance { AVLNew, // Not yet inserted in a tree
AVLLeft, // Left side is one deeper than the right
AVLBalanced, // Left and right sides are evenly balanced
AVLRight, // Right side is one deeper than left
};
template<class elementClass> class AVLElement;
template<class elementClass> class AVLTree {
public: AVLTree( unsigned preallocateSize = 0 );
~AVLTree( void );
elementClass *findFirstLessThanOrEqualTo( elementClass *element );
elementClass *findFirstGreaterThan( elementClass *element );
elementClass *findFirstGreaterThanOrEqualTo( elementClass *element );
elementClass *findMin( void );
elementClass *findMax( void );
int empty( void );
unsigned size( void );
void check( void );
BOOLEAN insert( elementClass *element );
void remove( elementClass *element );
void dumpPoolStats( void );
private:
AVLElement<elementClass> *tree;
Pool *avlElementPool;
unsigned insertions; unsigned deletions; unsigned singleRotations; unsigned doubleRotations;
friend class AVLElement<elementClass>; };
// The AVLElement class would normally be declared in the avl.cpp file, except that because it's
// a template, it needs to be in the header file. It can only be accessed (including creation and
// destruction) by the AVLTree friend class.
template<class elementClass> class AVLElement {
private:
AVLElement( void );
~AVLElement( void );
void initialize( void );
void insert( AVLTree<elementClass> *intoTree, elementClass *element );
void remove( AVLTree<elementClass> *fromTree );
unsigned checkAndReturnDepth( unsigned *countedElements );
int inTree( void );
int operator<=( AVLElement<elementClass> *peer);
int operator<( AVLElement<elementClass> *peer);
int operator==( AVLElement<elementClass> *peer);
int operator>=( AVLElement<elementClass> *peer);
int operator>( AVLElement<elementClass> *peer);
AVLElement<elementClass> *findFirstLessThanOrEqualTo( elementClass *element );
AVLElement<elementClass> *findFirstGreaterThan( elementClass *element );
AVLElement<elementClass> *findFirstGreaterThanOrEqualTo( elementClass *element );
void rightAdded( AVLTree<elementClass> *tree );
void leftAdded( AVLTree<elementClass> *tree );
void singleRotate( AVLTree<elementClass> *tree, AVLElement<elementClass> *child, AVLBalance whichSide );
void doubleRotate( AVLTree<elementClass> *tree, AVLElement<elementClass> *child, AVLElement<elementClass> *grandchild, AVLBalance whichSide );
void gotOneShorter( AVLTree<elementClass> *tree, AVLBalance whichSide );
AVLBalance balance;
AVLElement<elementClass> *left; AVLElement<elementClass> *right; AVLElement<elementClass> *parent; elementClass *element;
friend class AVLTree<elementClass>; };
template<class elementClass> elementClass * AVLTree<elementClass>::findFirstLessThanOrEqualTo( elementClass *element ) { assert( element ); if (!tree) return( NULL );
AVLElement<elementClass> *avlElement = tree->findFirstLessThanOrEqualTo( element ); if (avlElement) { return( avlElement->element ); } else { return( NULL ); } }
template<class elementClass> AVLTree<elementClass>::AVLTree( unsigned preallocateSize ) { tree = NULL; insertions = deletions = singleRotations = doubleRotations = 0; avlElementPool = new Pool( sizeof(AVLElement<elementClass>) ); if (preallocateSize && (NULL != avlElementPool)) { avlElementPool->preAllocate( preallocateSize ); } }
template<class elementClass> AVLTree<elementClass>::~AVLTree( void ) { assert( tree == NULL );
if (NULL != avlElementPool) { delete avlElementPool; } }
//****************************************************************************
//* *
//* Function: findFirstLessThanOrEqualTo *
//* *
//* Syntax: AVLElement * findFirstLessThanOrEqualTo( *
//* elementClass * element) *
//* *
//* Input: elementClass * element: *
//* A pointer to an element to compare against while searching. *
//* *
//* Output: AVLElement *: *
//* The element in the tree that has a value less than or equal *
//* to the one specified, or NULL on failure. *
//* *
//* Synopsis: This function finds the element in the tree that has a value *
//* less than or equal to the one specified. *
//* *
//****************************************************************************
template<class elementClass> AVLElement<elementClass> * AVLElement<elementClass>::findFirstLessThanOrEqualTo( elementClass * element ) { AVLElement<elementClass> * retVal = NULL;
if (*this->element == element) { // We have a direct match (equal to). It takes precidence over the
// "first less than" part.
return this; } if (*this->element < element) { // The current element is smaller than the one specified.
// This might be it, but try to find a bigger one.
if (right != NULL) { retVal = right->findFirstLessThanOrEqualTo( element ); }
// If nothing below us (to the right) was found, then we are the
// next smallest one.
if (retVal == NULL) { return this; } else { return retVal; } } else { // The current element is bigger than the one specified.
// We have to find a smaller one.
if (left != NULL) { return left->findFirstLessThanOrEqualTo( element ); } else { return NULL; } } }
template<class elementClass> elementClass * AVLTree<elementClass>::findFirstGreaterThan( elementClass *element ) { assert( element ); if (!tree) return( NULL );
AVLElement<elementClass> *avlElement = tree->findFirstGreaterThan( element );
if (avlElement) { return( avlElement->element ); } else { return( NULL ); } }
//****************************************************************************
//* *
//* Function: findFirstGreaterThan *
//* *
//* Syntax: AVLElement * findFirstGreaterThan(elementClass * element) *
//* *
//* Input: elementClass * element: *
//* A pointer to an element to compare against while searching. *
//* *
//* Output: AVLElement *: *
//* The element in the tree that has a vlaue greater than the *
//* one specified, or NULL on failure. *
//* *
//* Synopsis: This function finds the element in the tree that has a value *
//* greater than the one specified. *
//* *
//****************************************************************************
template<class elementClass> AVLElement<elementClass> * AVLElement<elementClass>::findFirstGreaterThan( elementClass * element ) { AVLElement<elementClass> * retVal = NULL;
if (*this->element > element) { // The current element is bigger than the one specified.
// This might be it, but try to find a smaller one.
if (left != NULL) { retVal = left->findFirstGreaterThan( element ); }
// If nothing below us (to the left) was found, then we are the
// next biggest one.
if (retVal == NULL) { return this; } else { return retVal; } } else { // The current element is smaller than (or equal) the one specified.
// We have to find a bigger one.
if (right != NULL) { return right->findFirstGreaterThan( element ); } else { return NULL; } } }
template<class elementClass> elementClass * AVLTree<elementClass>::findFirstGreaterThanOrEqualTo( elementClass *element ) { assert( element ); if (!tree) return( NULL );
AVLElement<elementClass> *avlElement = tree->findFirstGreaterThanOrEqualTo( element );
if (avlElement) { return( avlElement->element ); } else { return( NULL ); } }
//****************************************************************************
//* *
//* Function: findFirstGreaterThanOrEqualTo *
//* *
//* Syntax: AVLElement * findFirstGreaterThanOrEqualTo(elementClass * element)
//* *
//* Input: elementClass * element: *
//* A pointer to an element to compare against while searching. *
//* *
//* Output: AVLElement *: *
//* The element in the tree that has a vlaue greater than or *
//* equal to the one specified, or NULL on failure. *
//* *
//* Synopsis: This function finds the element in the tree that has a value *
//* greater than or equal to the one specified. *
//* *
//****************************************************************************
template<class elementClass> AVLElement<elementClass> * AVLElement<elementClass>::findFirstGreaterThanOrEqualTo( elementClass * element ) { if (*this->element == element) { // We have a direct match (equal to). It takes precidence over the
// "first less than" part.
return this; }
AVLElement<elementClass> * retVal = NULL;
if (*this->element > element) { // The current element is bigger than the one specified.
// This might be it, but try to find a smaller one.
if (left != NULL) { retVal = left->findFirstGreaterThanOrEqualTo( element ); }
// If nothing below us (to the left) was found, then we are the
// next biggest one.
if (retVal == NULL) { return this; } else { return retVal; } } else { // The current element is strictly smaller than the one specified.
// We have to find a bigger one.
if (right != NULL) { return right->findFirstGreaterThanOrEqualTo( element ); } else { return NULL; } } }
template<class elementClass> int AVLTree<elementClass>::empty( void ) { assert( (tree == NULL) == (insertions == deletions) ); return( tree == NULL ); }
template<class elementClass> unsigned AVLTree<elementClass>::size( void ) { assert( insertions >= deletions ); assert( (tree == NULL) == (insertions == deletions) ); return( insertions - deletions ); }
template<class elementClass> elementClass * AVLTree<elementClass>::findMin( void ) { if (!tree) { return( NULL ); }
AVLElement<elementClass> *candidate = tree; while (candidate->left) { assert( *candidate->left->element <= candidate->element ); candidate = candidate->left; } return( candidate->element ); }
template<class elementClass> elementClass * AVLTree<elementClass>::findMax( void ) { if (!tree) { return( NULL ); }
AVLElement<elementClass> *candidate = tree; while (candidate->right) { assert( *candidate->right->element >= candidate->element ); candidate = candidate->right; } return( candidate->element ); }
template<class elementClass> void AVLTree<elementClass>::check( void ) { AVLElement<elementClass> * currElement = NULL; AVLElement<elementClass> * nextElement = NULL; AVLElement<elementClass> * oldElement = NULL;
unsigned countedElements = 0; if (tree) { assert( tree->parent == NULL ); unsigned overallDepth = tree->checkAndReturnDepth( &countedElements ); } assert( insertions-deletions == countedElements );
// Check every element in the tree for consistance by verifying that it is in
// the expected order. If not, it is most likely that the element's operators
// are not behaving as needed.
for(currElement = tree; currElement != NULL; currElement = nextElement) { // Go left if we can (and have not already been here).
if (currElement->left && oldElement == currElement->parent) { nextElement = currElement->left; assert( *nextElement < currElement && "The < operator appears to be broken" ); assert( *currElement > nextElement && "The > operator appears to be broken" ); assert( !(*nextElement == currElement) && "The == operator appears to be broken" ); } // Otherwise go right if we can (and have not already been here).
else if (currElement->right && (oldElement == currElement->left || oldElement == currElement->parent)) { nextElement = currElement->right; assert( *nextElement > currElement && "The > operator appears to be broken" ); assert( *currElement < nextElement && "The < operator appears to be broken" ); assert( !(*nextElement == currElement) && "The == operator appears to be broken" ); } // We are done below us, go up a node.
else { nextElement = currElement->parent; }
oldElement = currElement; assert( *oldElement == currElement && "The == operator appears to be broken" ); } }
template<class elementClass> AVLElement<elementClass>::AVLElement( void ) { balance = AVLNew; left = right = parent = NULL; }
template<class elementClass> AVLElement<elementClass>::~AVLElement( void ) { assert( balance == AVLNew ); assert( left == NULL && right == NULL && parent == NULL ); }
template<class elementClass> unsigned AVLElement<elementClass>::checkAndReturnDepth( unsigned *countedElements ) { // We've been inserted and not deleted
assert( balance != AVLNew );
(*countedElements)++;
// Assert that the links all match up.
assert( !left || left->parent == this ); assert( !right || right->parent == this );
// The basic binary tree ordering property applies
assert( !right || *this <= right ); assert( !left || *this >= left );
// The AVL balance property applies
unsigned leftDepth; if (left) { leftDepth = left->checkAndReturnDepth( countedElements ); } else { leftDepth = 0; }
unsigned rightDepth; if (right) { rightDepth = right->checkAndReturnDepth( countedElements ); } else { rightDepth = 0; }
if (leftDepth == rightDepth) { assert( balance == AVLBalanced ); return( leftDepth + 1 ); }
if (leftDepth == rightDepth + 1) { assert( balance == AVLLeft ); return( leftDepth + 1 ); }
if (leftDepth + 1 == rightDepth) { assert( balance == AVLRight ); return( rightDepth + 1 ); }
assert( !"AVL Tree out of balance" ); return( 0 ); }
template<class elementClass> void AVLElement<elementClass>::insert( AVLTree<elementClass> *intoTree, elementClass *element ) { assert( intoTree ); assert( left == NULL && right == NULL && parent == NULL );
this->element = element; assert( this->element );
intoTree->insertions++;
// Special case the empty tree case.
if (intoTree->tree == NULL) { intoTree->tree = this; balance = AVLBalanced; // We already know all of the links are NULL, which is correct for this case.
return; }
// Find the leaf position at which to do this insertion.
AVLElement *currentNode = intoTree->tree; AVLElement *previousNode = NULL; while (currentNode) { previousNode = currentNode; if (*currentNode < this) { currentNode = currentNode->right; } else if (*currentNode > this) { currentNode = currentNode->left; } else { // An AVL tree gets all whacky if you try to insert duplicate values.
assert( !"Trying to insert a duplicate item. Use something other than an AVL tree." ); } }
balance = AVLBalanced; parent = previousNode; assert( parent ); if (*previousNode <= this) { assert( !previousNode->right ); previousNode->right = this; previousNode->rightAdded( intoTree ); // intoTree->check();
} else { assert( !previousNode->left ); previousNode->left = this; previousNode->leftAdded( intoTree ); // intoTree->check();
} }
template<class elementClass> void AVLElement<elementClass>::rightAdded( AVLTree<elementClass> *tree ) { //We've just gotten one deeper on our right side.
assert( balance != AVLNew );
if (balance == AVLLeft) { balance = AVLBalanced; // The depth of the subtree rooted here hasn't changed, we're done
return; } if (balance == AVLBalanced) { // We've just gotten one deeper, but are still balanced. Update and recurse up the
// tree.
balance = AVLRight; if (parent) { if (parent->right == this) { parent->rightAdded( tree ); } else { assert( parent->left == this ); parent->leftAdded( tree ); } } return; } assert( balance == AVLRight ); // We've just gone to double right (ie, out of balance).
assert( right ); if (right->balance == AVLRight) { singleRotate( tree,right,AVLRight ); } else { assert( right->balance == AVLLeft ); // Else we shouldn't have been AVLRight before the call
doubleRotate( tree,right,right->left,AVLRight ); } }
template<class elementClass> void AVLElement<elementClass>::leftAdded( AVLTree<elementClass> *tree ) { //We've just gotten one deeper on our right side.
assert( balance != AVLNew );
if (balance == AVLRight) { balance = AVLBalanced; // The depth of the subtree rooted here hasn't changed, we're done
return; } if (balance == AVLBalanced) { // We've just gotten one deeper, but are still balanced. Update and recurse up the
// tree.
balance = AVLLeft; if (parent) { if (parent->right == this) { parent->rightAdded( tree ); } else { assert( parent->left == this ); parent->leftAdded( tree ); } } return; } assert( balance == AVLLeft ); // We've just gone to double left (ie, out of balance).
assert( left ); if (left->balance == AVLLeft) { singleRotate( tree,left,AVLLeft ); } else { assert( left->balance == AVLRight ); // Else we shouldn't have been AVLLeft before the call
doubleRotate( tree,left,left->right,AVLLeft ); } }
template<class elementClass> void AVLElement<elementClass>::singleRotate( AVLTree<elementClass> *tree, AVLElement *child, AVLBalance whichSide ) { // We're the parent node.
assert( tree ); assert( child ); assert( whichSide == AVLRight || whichSide == AVLLeft );
assert( whichSide != AVLRight || right == child ); assert( whichSide != AVLLeft || left == child );
tree->singleRotations++;
// Promote the child to our position in the tree.
if (parent) { if (parent->left == this) { parent->left = child; child->parent = parent; } else { assert( parent->right == this ); parent->right = child; child->parent = parent; } } else { // We're the root of the tree
assert( tree->tree == this ); tree->tree = child; child->parent = NULL; }
// Attach the child's light subtree to our heavy side (ie., where the child is attached now)
// Then, attach us to the child's light subtree
if (whichSide == AVLRight) { right = child->left; if (right) { right->parent = this; }
child->left = this; parent = child; } else { left = child->right; if (left) { left->parent = this; }
child->right = this; parent = child; }
// Finally, now both our and our (former) child's balance is "balanced"
balance = AVLBalanced; child->balance = AVLBalanced; // NB. One of the cases in delete will result in the above balance settings being incorrect. That
// case fixes up the settings after we return.
}
template<class elementClass> void AVLElement<elementClass>::doubleRotate( AVLTree<elementClass> *tree, AVLElement *child, AVLElement *grandchild, AVLBalance whichSide ) { assert( tree && child && grandchild ); assert( whichSide == AVLLeft || whichSide == AVLRight );
assert( whichSide != AVLLeft || (left == child && child->balance == AVLRight) ); assert( whichSide != AVLRight || (right == child && child->balance == AVLLeft) );
assert( child->parent == this ); assert( grandchild->parent == child );
tree->doubleRotations++;
// Write down a copy of all of the subtrees; see Knuth v3 p454 for the picture.
// NOTE: The alpha and delta trees are never moved, so we don't store them.
AVLElement *beta; AVLElement *gamma;
if (whichSide == AVLRight) { beta = grandchild->left; gamma = grandchild->right; } else { beta = grandchild->right; gamma = grandchild->left; }
// Promote grandchild to our position
if (parent) { if (parent->left == this) { parent->left = grandchild; } else { assert( parent->right == this ); parent->right = grandchild; } } else { assert( tree->tree == this ); tree->tree = grandchild; } grandchild->parent = parent;
// Attach the appropriate children to grandchild
if (whichSide == AVLRight) { grandchild->right = child; grandchild->left = this; } else { grandchild->right = this; grandchild->left = child; } parent = grandchild; child->parent = grandchild;
// Attach beta and gamma to us and child.
if (whichSide == AVLRight) { right = beta; if (beta) { beta->parent = this; } child->left = gamma; if (gamma) { gamma->parent = child; } } else { left = beta; if (beta) { beta->parent = this; } child->right = gamma; if (gamma) { gamma->parent = child; } }
// Now update the balance fields.
switch (grandchild->balance) { case AVLLeft: if (whichSide == AVLRight) { balance = AVLBalanced; child->balance = AVLRight; } else { balance = AVLRight; child->balance = AVLBalanced; } break;
case AVLBalanced: balance = AVLBalanced; child->balance = AVLBalanced; break;
case AVLRight: if (whichSide == AVLRight) { balance = AVLLeft; child->balance = AVLBalanced; } else { balance = AVLBalanced; child->balance = AVLLeft; } break;
default: assert( !"Bogus balance value" ); } grandchild->balance = AVLBalanced; }
template<class elementClass> void AVLElement<elementClass>::remove( AVLTree<elementClass> *fromTree ) { assert( fromTree ); assert( balance == AVLRight || balance == AVLLeft || balance == AVLBalanced );
fromTree->deletions++;
if (left == NULL) { // The right child either doesn't exist or is a leaf (because of the AVL balance property)
assert( (!right && balance == AVLBalanced) || (balance == AVLRight && right->balance == AVLBalanced && right->right == NULL && right->left == NULL) ); if (right) { right->parent = parent; } if (parent) { if (parent->left == this) { parent->left = right; parent->gotOneShorter( fromTree,AVLLeft ); } else { assert( parent->right == this ); parent->right = right; parent->gotOneShorter( fromTree,AVLRight ); } } else { assert( fromTree->tree == this ); fromTree->tree = right; } } else if (right == NULL) { // The left child must be a left because of the AVL balance property
assert( left && balance == AVLLeft && left->balance == AVLBalanced && left->right == NULL && left->left == NULL ); left->parent = parent; if (parent) { if (parent->left == this) { parent->left = left; parent->gotOneShorter( fromTree,AVLLeft ); } else { assert( parent->right == this ); parent->right = left; parent->gotOneShorter( fromTree,AVLRight ); } } else { assert( fromTree->tree == this ); fromTree->tree = left; } } else { // Find the symmetric successor and promote it. The symmetric successor is the smallest element in the right
// subtree; it's found by following all left links in the right subtree until we find a node with no left link.
// That node may be promoted to the place of this without corrupting the binary tree ordering properties. (We could
// just as easily use the symmetric predecessor by finding the largest element in the right subtree, but there's
// no point.)
AVLElement *successorCandidate = right; while (successorCandidate->left) { successorCandidate = successorCandidate->left; }
AVLElement *shorterRoot; AVLBalance shorterSide; if (successorCandidate->parent->left == successorCandidate) { // We need to promote the successor's child (if any) to its position, then
// promote it to our position.
shorterRoot = successorCandidate->parent; shorterSide = AVLLeft; successorCandidate->parent->left = successorCandidate->right; if (successorCandidate->right) { successorCandidate->right->parent = successorCandidate->parent; }
successorCandidate->right = right; successorCandidate->left = left; successorCandidate->balance = balance; successorCandidate->right->parent = successorCandidate; successorCandidate->left->parent = successorCandidate; if (parent) { if (parent->left == this) { parent->left = successorCandidate; } else { assert( parent->right == this ); parent->right = successorCandidate; } } else { assert( fromTree->tree == this ); fromTree->tree = successorCandidate; } successorCandidate->parent = parent; } else { // The successor was our child, just directly promote it.
assert( successorCandidate->parent == this ); if (parent) { if (parent->right == this) { parent->right = successorCandidate; } else { assert( parent->left == this ); parent->left = successorCandidate; } } else { assert( fromTree->tree == this ); fromTree->tree = successorCandidate; } successorCandidate->parent = parent; successorCandidate->left = left; if (left) { left->parent = successorCandidate; } // We just made our right subtree shorter.
successorCandidate->balance = balance; shorterRoot = successorCandidate; shorterSide = AVLRight; } if (shorterRoot) { shorterRoot->gotOneShorter( fromTree,shorterSide ); } }
balance = AVLNew; left = right = parent = NULL; element = NULL; // fromTree->check();
}
template<class elementClass> void AVLElement<elementClass>::gotOneShorter( AVLTree<elementClass> *tree, AVLBalance whichSide ) { assert( whichSide == AVLLeft || whichSide == AVLRight );
if (balance == AVLBalanced) { // We've just shrunk one subttree, but our depth has stayed the same.
// Reset our balance indicator and punt.
if (whichSide == AVLRight) { balance = AVLLeft; } else { balance = AVLRight; } return; } else if (balance == whichSide) { // We just shrunk our heavy side; set our balance to neutral and recurse up the tree
balance = AVLBalanced; if (parent) { if (parent->right == this) { parent->gotOneShorter( tree,AVLRight ); } else { assert( parent->left == this ); parent->gotOneShorter( tree,AVLLeft ); } } // else we were the root; we're done
return; } else { // We've just gone out of balance. Figure out a rotation to do. This is almost like having added a
// node to the opposide side, except that the opposite side might be balanced.
AVLBalance heavySide; AVLElement *heavyChild; AVLElement *replacement; if (whichSide == AVLRight) { heavySide = AVLLeft; heavyChild = left; } else { heavySide = AVLRight; heavyChild = right; } assert( heavyChild ); if (heavyChild->balance == heavySide) { // Typical single rotation case
singleRotate( tree,heavyChild,heavySide ); replacement = heavyChild; } else if (heavyChild->balance == whichSide) { // Typical double rotation case
AVLElement *grandchild; if (heavySide == AVLRight) { grandchild = heavyChild->left; } else { grandchild = heavyChild->right; } doubleRotate( tree,heavyChild,grandchild,heavySide ); replacement = grandchild; } else { assert( heavyChild->balance == AVLBalanced ); singleRotate( tree,heavyChild,heavySide ); // singleRotate has incorrectly set the balances; reset them
balance = heavySide; heavyChild->balance = whichSide; // Overall depth hasn't changed; we're done.
return; }
// NB: we have now changed position in the tree, so parent, right & left have changed!
if (!replacement->parent) { // We just promoted our replacement to the root; we be done
return; } if (replacement->parent->right == replacement) { replacement->parent->gotOneShorter( tree,AVLRight ); } else { assert( replacement->parent->left == replacement ); replacement->parent->gotOneShorter( tree,AVLLeft ); }
} }
template<class elementClass> int AVLElement<elementClass>::inTree( void ) { return( balance != AVLNew ); }
template <class elementClass> int AVLElement<elementClass>::operator<=( AVLElement<elementClass> *peer) { return( *element <= peer->element ); }
template <class elementClass> int AVLElement<elementClass>::operator<( AVLElement<elementClass> *peer) { return( *element < peer->element ); }
template <class elementClass> int AVLElement<elementClass>::operator==( AVLElement<elementClass> *peer) { return( *element == peer->element ); }
template <class elementClass> int AVLElement<elementClass>::operator>=( AVLElement<elementClass> *peer) { return( *element >= peer->element ); }
template <class elementClass> int AVLElement<elementClass>::operator>( AVLElement<elementClass> *peer) { return( *element > peer->element ); }
template <class elementClass> BOOLEAN AVLTree<elementClass>::insert( elementClass *element ) { if (NULL == avlElementPool) { return FALSE; }
assert( element ); AVLElement<elementClass> *avlElement = (AVLElement<elementClass> *)avlElementPool->allocate( ); if (NULL == avlElement) { return FALSE; }
avlElement->initialize( ); avlElement->insert( this,element );
return TRUE; }
template <class elementClass> void AVLTree<elementClass>::remove( elementClass *element ) { assert( element ); AVLElement<elementClass> *candidate = tree->findFirstLessThanOrEqualTo( element ); assert( candidate && *candidate->element == element ); candidate->remove( this ); assert( avlElementPool ); // if this isn't true, then we could never have had a successful insert
avlElementPool->free( (void *)candidate ); }
template <class elementClass> void AVLElement<elementClass>::initialize( void ) { balance = AVLNew; left = right = parent = NULL; element = NULL; }
template <class elementClass> void AVLTree<elementClass>::dumpPoolStats( void ) { if (NULL == avlElementPool) { DbgPrint( "Unable to allocate avlElementPool; this AVL tree is essentially useless\n" ); } else { DbgPrint( "AVLTree AVLElement pool: %d allocations, %d frees, %d news, objectSize %d\n", avlElementPool->numAllocations( ), avlElementPool->numFrees( ), avlElementPool->numNews( ), avlElementPool->getObjectSize( ) ); } }
|