|
|
/*++
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; 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()); } }
|