/*++ 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 AVLElement; template 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 *tree; Pool *avlElementPool; unsigned insertions; unsigned deletions; unsigned singleRotations; unsigned doubleRotations; friend class AVLElement; }; // 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 AVLElement { private: AVLElement( void ); ~AVLElement( void ); void initialize( void ); void insert( AVLTree *intoTree, elementClass *element ); void remove( AVLTree *fromTree ); unsigned checkAndReturnDepth( unsigned *countedElements ); int inTree( void ); int operator<=( AVLElement *peer); int operator<( AVLElement *peer); int operator==( AVLElement *peer); int operator>=( AVLElement *peer); int operator>( AVLElement *peer); AVLElement *findFirstLessThanOrEqualTo( elementClass *element ); AVLElement *findFirstGreaterThan( elementClass *element ); AVLElement *findFirstGreaterThanOrEqualTo( elementClass *element ); void rightAdded( AVLTree *tree ); void leftAdded( AVLTree *tree ); void singleRotate( AVLTree *tree, AVLElement *child, AVLBalance whichSide ); void doubleRotate( AVLTree *tree, AVLElement *child, AVLElement *grandchild, AVLBalance whichSide ); void gotOneShorter( AVLTree *tree, AVLBalance whichSide ); AVLBalance balance; AVLElement *left; AVLElement *right; AVLElement *parent; elementClass *element; friend class AVLTree; }; template elementClass * AVLTree::findFirstLessThanOrEqualTo( elementClass *element ) { assert( element ); if (!tree) return( NULL ); AVLElement *avlElement = tree->findFirstLessThanOrEqualTo( element ); if (avlElement) { return( avlElement->element ); } else { return( NULL ); } } template AVLTree::AVLTree( unsigned preallocateSize ) { tree = NULL; insertions = deletions = singleRotations = doubleRotations = 0; avlElementPool = new Pool( sizeof(AVLElement) ); if (preallocateSize && (NULL != avlElementPool)) { avlElementPool->preAllocate( preallocateSize ); } } template AVLTree::~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 AVLElement * AVLElement::findFirstLessThanOrEqualTo( elementClass * element ) { AVLElement * 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 elementClass * AVLTree::findFirstGreaterThan( elementClass *element ) { assert( element ); if (!tree) return( NULL ); AVLElement *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 AVLElement * AVLElement::findFirstGreaterThan( elementClass * element ) { AVLElement * 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 elementClass * AVLTree::findFirstGreaterThanOrEqualTo( elementClass *element ) { assert( element ); if (!tree) return( NULL ); AVLElement *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 AVLElement * AVLElement::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 * 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 int AVLTree::empty( void ) { assert( (tree == NULL) == (insertions == deletions) ); return( tree == NULL ); } template unsigned AVLTree::size( void ) { assert( insertions >= deletions ); assert( (tree == NULL) == (insertions == deletions) ); return( insertions - deletions ); } template elementClass * AVLTree::findMin( void ) { if (!tree) { return( NULL ); } AVLElement *candidate = tree; while (candidate->left) { assert( *candidate->left->element <= candidate->element ); candidate = candidate->left; } return( candidate->element ); } template elementClass * AVLTree::findMax( void ) { if (!tree) { return( NULL ); } AVLElement *candidate = tree; while (candidate->right) { assert( *candidate->right->element >= candidate->element ); candidate = candidate->right; } return( candidate->element ); } template void AVLTree::check( void ) { AVLElement * currElement = NULL; AVLElement * nextElement = NULL; AVLElement * 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 AVLElement::AVLElement( void ) { balance = AVLNew; left = right = parent = NULL; } template AVLElement::~AVLElement( void ) { assert( balance == AVLNew ); assert( left == NULL && right == NULL && parent == NULL ); } template unsigned AVLElement::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 void AVLElement::insert( AVLTree *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 void AVLElement::rightAdded( AVLTree *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 void AVLElement::leftAdded( AVLTree *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 void AVLElement::singleRotate( AVLTree *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 void AVLElement::doubleRotate( AVLTree *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 void AVLElement::remove( AVLTree *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 void AVLElement::gotOneShorter( AVLTree *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 int AVLElement::inTree( void ) { return( balance != AVLNew ); } template int AVLElement::operator<=( AVLElement *peer) { return( *element <= peer->element ); } template int AVLElement::operator<( AVLElement *peer) { return( *element < peer->element ); } template int AVLElement::operator==( AVLElement *peer) { return( *element == peer->element ); } template int AVLElement::operator>=( AVLElement *peer) { return( *element >= peer->element ); } template int AVLElement::operator>( AVLElement *peer) { return( *element > peer->element ); } template BOOLEAN AVLTree::insert( elementClass *element ) { if (NULL == avlElementPool) { return FALSE; } assert( element ); AVLElement *avlElement = (AVLElement *)avlElementPool->allocate( ); if (NULL == avlElement) { return FALSE; } avlElement->initialize( ); avlElement->insert( this,element ); return TRUE; } template void AVLTree::remove( elementClass *element ) { assert( element ); AVLElement *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 void AVLElement::initialize( void ) { balance = AVLNew; left = right = parent = NULL; element = NULL; } template void AVLTree::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( ) ); } }