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