/*========================================================================== _____ .__ .__ / \ ____ _____| |__ __ __| | _____ / \ / \_/ __ \ / ___/ | \| | \ | \__ \ / Y \ ___/ \___ \| Y \ | / |__/ __ \_ \____|__ /\___ >____ >___| /____/|____(____ / \/ \/ \/ \/ \/ _________ ____.____ ___________ / _ \ \ / /| | \__ ___/______ ____ ____ / /_\ \ Y / | | | | \_ __ \_/ __ \_/ __ \ / | \ / | |___ | | | | \/\ ___/\ ___/ \____|__ /\___/ |_______ \ |____| |__| \___ >\___ > \/ \/ \/ \/ with thanks to - Greig McLachlan of http://www.learntoprogram.com for providing a clean implementation of Insert which I used as a starting point Jason F Boxall of CSC330 who posted his assignment on the web, I double checked my Remove implementation against his. R Levow of http://www.cse.fau.edu/~roy/cop3530.98f/prog5-BSTIterator.html who posted an algorithm for creating binary tree iterators http://meshula.artistnation.com 2002 The template is free for use, no warrantee or suitability for any particular purpose is expressed or implied. Verify that it works the way you expect before you incorporate it into your own project. public interface - AVL(); ~AVL(); bool Insert(KeyType key, ItemType item); bool Remove(KeyType key); bool Find(KeyType key, ItemType& item); short GetDepth() Iterator(Iterator*) Iterator(AVL*) ~Iterator() // all return true for success, false for failure or end of tree bool GetFirst(KeyType& key, ItemType& item) bool GetNext(KeyType& key, ItemType& item) bool GetCurrent(KeyType& key, ItemType& item) bool Find(KeyType key, ItemType& item) ==========================================================================*/ /*-------------------------------------------------------------------------------------------- ___ ___ _ _ _ _ / \ \ / / | __| | ___ ___| | __ _ _ __ __ _| |_(_) ___ _ __ / _ \ \ / /| | / _` |/ _ \/ __| |/ _` | '__/ _` | __| |/ _ \| '_ \ / ___ \ V / | |___ | (_| | __/ (__| | (_| | | | (_| | |_| | (_) | | | | /_/ \_\_/ |_____| \__,_|\___|\___|_|\__,_|_| \__,_|\__|_|\___/|_| |_| --------------------------------------------------------------------------------------------*/ template class AVL { protected: template class AVLNode { public: AVLNode(KeyType key, ItemType item) : m_Balance(0), m_Depth(0), m_Key(key), m_Data(item), m_pLeft(0), m_pRight(0) { } short m_Balance; short m_Depth; KeyType m_Key; ItemType m_Data; AVLNode* m_pLeft; AVLNode* m_pRight; }; AVLNode* m_pRoot; public: /*------------------------------------------------------------------------ _ _ _ _ _ __ _ __ _ _| |__ | (_) ___ (_)_ __ | |_ ___ _ __ / _| __ _ ___ ___ | '_ \| | | | '_ \| | |/ __| | | '_ \| __/ _ \ '__| |_ / _` |/ __/ _ \ | |_) | |_| | |_) | | | (__ | | | | | || __/ | | _| (_| | (_| __/ | .__/ \__,_|_.__/|_|_|\___| |_|_| |_|\__\___|_| |_| \__,_|\___\___| |_| */ AVL() : m_pRoot(0) { } ~AVL() { } void Insert(KeyType key, ItemType item); void Remove(KeyType key); bool Find (KeyType key, ItemType& item); short GetDepth() const { return (m_pRoot ? m_pRoot->m_Depth : 0); } /*------------------------------------------------------------------------ _ _ _ (_) |_ ___ _ __ __ _| |_ ___ _ __ | | __/ _ \ '__/ _` | __/ _ \| '__| | | || __/ | | (_| | || (_) | | |_|\__\___|_| \__,_|\__\___/|_| */ template class Iterator { #define kMaxAVLDepth 32 public: Iterator(Iterator* pCopyMe) : mpAVL(pCopyMe->mpAVL), mpCurr(pCopyMe->mpCurr) { mTraversalStackIndex = pCopyMe->mTraversalStackIndex; for (int i = 0; i < mTraversalStackIndex; ++i) mTraversalStack[i] = pCopyMe->mTraversalStack[i]; } Iterator(AVL* pTree) : mpAVL(pTree) { KeyType key; ItemType item; GetFirst(key, item); } ~Iterator() { } bool GetCurrent(KeyType& key, ItemType& item) { if (mpCurr) { key = mpCurr->m_Key; item = mpCurr->m_Data; return true; } else return false; } // returns false if the tree is empty bool GetFirst (KeyType& key, ItemType& item) { mTraversalStackIndex = 0; if (!mpAVL->m_pRoot) { mpCurr = 0; item = 0; return false; } else { AVLNode* pCurr = mpAVL->m_pRoot; AVLNode* pPrev = pCurr; while (pCurr) { pPrev = pCurr; if (pCurr->m_pLeft) mTraversalStack[mTraversalStackIndex++] = pCurr; pCurr = pCurr->m_pLeft; } mpCurr = pPrev; key = mpCurr->m_Key; item = mpCurr->m_Data; return true; } } bool GetNext (KeyType& key, ItemType& item) { if (!mpCurr) // already done? { item = 0; return false; } else { AVLNode* pCurr = mpCurr->m_pRight; // start looking to the right while (true) // this while forces a traversal as far left as possible { if (pCurr) // if we have a pcurr, push it and go left, and repeat. { mTraversalStack[mTraversalStackIndex++] = pCurr; pCurr = pCurr->m_pLeft; } else // backtrack { if (mTraversalStackIndex > 0) { AVLNode* pCandidate = mTraversalStack[--mTraversalStackIndex]; // did we backtrack up a right branch? if (mpCurr == pCandidate->m_pRight) { // if there is a parent, return the parent. if (mTraversalStackIndex > 0) { mpCurr = mTraversalStack[--mTraversalStackIndex]; key = mpCurr->m_Key; item = mpCurr->m_Data; return true; } else // if up a right branch, and no parent, traversal finished { mpCurr = 0; item = 0; return false; } } else // up a left branch, done. { mpCurr = pCandidate; key = mpCurr->m_Key; item = mpCurr->m_Data; return true; } } else // totally done { mpCurr = 0; item = 0; return false; } } } } } bool Find (KeyType key, ItemType& item) { AVLNode* pCurr = mpAVL->m_pRoot; mTraversalStackIndex = 0; while (true) { AVLNode* pPushMe = pCurr; if (pCurr->m_Key == key) // already done? { mpCurr = pCurr; item = mpCurr->m_Data; return true; } if (pCurr->m_Key > key) pCurr = pCurr->m_pLeft; else pCurr = pCurr->m_pRight; if (pCurr) // maintain the stack so that GetNext will work. { mTraversalStack[mTraversalStackIndex++] = pPushMe; } else // couldn't find it. { mpCurr = 0; mTraversalStackIndex = 0; return false; } } return true; } protected: AVL* mpAVL; AVLNode* mTraversalStack[kMaxAVLDepth]; short mTraversalStackIndex; AVLNode* mpCurr; // for iteration }; friend class AVL::Iterator; protected: void _Insert (KeyType key, ItemType item, AVLNode*& root); void _Remove (AVLNode*& root, KeyType key, bool& delOK); void _RemoveBothChildren (AVLNode*& root, AVLNode*& curr, bool& delOK); bool _Find (KeyType key, ItemType& item, AVLNode* root); void ComputeBalance (AVLNode* root); void Balance (AVLNode*& root); void BalanceRight (AVLNode*& root); void BalanceLeft (AVLNode*& root); void RotateLeft (AVLNode*& root); void RotateRight (AVLNode*& root); }; /*-------------------------------------------------------------------------------------------- _ _ _ (_)_ __ ___ ___ _ __| |_(_) ___ _ __ | | '_ \/ __|/ _ \ '__| __| |/ _ \| '_ \ | | | | \__ \ __/ | | |_| | (_) | | | | |_|_| |_|___/\___|_| \__|_|\___/|_| |_| --------------------------------------------------------------------------------------------*/ template void AVL::Insert(KeyType key, ItemType item) { if (m_pRoot == 0) { m_pRoot = new AVLNode(key, item); } else _Insert(key, item, m_pRoot); } template void AVL::_Insert(KeyType key, ItemType item, AVLNode*& root) { if (key < root->m_Key) { if (root->m_pLeft) _Insert(key, item, root->m_pLeft); else root->m_pLeft = new AVLNode(key, item); } else if (key > root->m_Key) { if (root->m_pRight) _Insert(key, item, root->m_pRight); else root->m_pRight = new AVLNode(key, item); } else { // error - can't have duplicate keys. // if duplicate keys are okay, change key < to key <= above } ComputeBalance(root); Balance(root); } /*-------------------------------------------------------------------------------------------- _ _ __ ___ _ __ ___ _____ ____ _| | | '__/ _ \ '_ ` _ \ / _ \ \ / / _` | | | | | __/ | | | | | (_) \ V / (_| | | |_| \___|_| |_| |_|\___/ \_/ \__,_|_| --------------------------------------------------------------------------------------------*/ template void AVL::Remove(KeyType key) { bool delOK = false; _Remove(m_pRoot, key, delOK); } template void AVL::_Remove(AVLNode*& root, KeyType key, bool& delOK) { if (!root) { delOK = false; } else if (root->m_Key > key) // go to left subtree { _Remove(root->m_pLeft, key, delOK); if (delOK) { ComputeBalance(root); BalanceRight(root); } } else if (root->m_Key < key) // go to right subtree { _Remove(root->m_pRight, key, delOK); if (delOK) { ComputeBalance(root); BalanceLeft(root); } } else // node found! { AVLNode* pMe = root; if (!root->m_pRight) { root = root->m_pLeft; delOK = true; delete pMe; } else if (!root->m_pLeft) { root = root->m_pRight; delOK = true; delete pMe; } else { _RemoveBothChildren(root, root->m_pLeft, delOK); if (delOK) { ComputeBalance(root); Balance(root); } delOK = true; } } } template void AVL::_RemoveBothChildren(AVLNode*& root, AVLNode*& curr, bool& delOK) { if (!curr->m_pRight) { root->m_Key = curr->m_Key; root->m_Data = curr->m_Data; AVLNode* pMe = curr; curr = curr->m_pLeft; delete pMe; delOK = true; } else { _RemoveBothChildren(root, curr->m_pRight, delOK); if (delOK) { ComputeBalance(root); Balance(root); } } } /*-------------------------------------------------------------------------------------------- _ _ ___ ___ __ _ _ __ ___| |__ (_)_ __ __ _ / __|/ _ \/ _` | '__/ __| '_ \| | '_ \ / _` | \__ \ __/ (_| | | | (__| | | | | | | | (_| | |___/\___|\__,_|_| \___|_| |_|_|_| |_|\__, | |___/ --------------------------------------------------------------------------------------------*/ template bool AVL::Find(KeyType key, ItemType& item) { return _Find(key, item, m_pRoot); } template bool AVL::_Find(KeyType key, ItemType& item, AVLNode* root) { if (root) { if (root->m_Key == key) { item = root->m_Data; return true; } if (key < root->m_Key) return _Find(key, item, root->m_pLeft); else return _Find(key, item, root->m_pRight); } else { return false; } } /*-------------------------------------------------------------------------------------------- _ _ _ | |__ __ _| | __ _ _ __ ___(_)_ __ __ _ | '_ \ / _` | |/ _` | '_ \ / __| | '_ \ / _` | | |_) | (_| | | (_| | | | | (__| | | | | (_| | |_.__/ \__,_|_|\__,_|_| |_|\___|_|_| |_|\__, | |___/ --------------------------------------------------------------------------------------------*/ template void AVL::ComputeBalance(AVLNode* root) { if (root) { short leftDepth = root->m_pLeft ? root->m_pLeft->m_Depth : 0; short rightDepth = root->m_pRight ? root->m_pRight->m_Depth : 0; root->m_Depth = 1 + ((leftDepth > rightDepth) ? leftDepth : rightDepth); root->m_Balance = rightDepth - leftDepth; } } template void AVL::Balance(AVLNode*& root) { // AVL trees have the property that no branch is more than 1 longer than its sibling if (root->m_Balance > 1) BalanceRight(root); if (root->m_Balance < -1) BalanceLeft(root); } template void AVL::BalanceRight(AVLNode*& root) { if (root->m_pRight) { if (root->m_pRight->m_Balance > 0) { RotateLeft(root); } else if (root->m_pRight->m_Balance < 0) { RotateRight(root->m_pRight); RotateLeft(root); } } } template void AVL::BalanceLeft(AVLNode*& root) { if (root->m_pLeft) { if (root->m_pLeft->m_Balance < 0) { RotateRight(root); } else if (root->m_pLeft->m_Balance > 0) { RotateLeft(root->m_pLeft); RotateRight(root); } } } template void AVL::RotateLeft(AVLNode*& root) { AVLNode* pTemp = root; root = root->m_pRight; pTemp->m_pRight = root->m_pLeft; root->m_pLeft = pTemp; ComputeBalance(root->m_pLeft); ComputeBalance(root->m_pRight); ComputeBalance(root); } template void AVL::RotateRight(AVLNode*& root) { AVLNode* pTemp = root; root = root->m_pLeft; pTemp->m_pLeft = root->m_pRight; root->m_pRight = pTemp; ComputeBalance(root->m_pLeft); ComputeBalance(root->m_pRight); ComputeBalance(root); }