/* ---- This file is part of SECONDO. Copyright (C) 2004, University in Hagen, Department of Computer Science, Database Systems for New Applications. SECONDO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SECONDO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with SECONDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---- //paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}] //[TOC] [\tableofcontents] //[_] [\_] [1] Header File containing for the template class ~AvlTree~ [TOC] 1 Overview This header file contains the classes for the classes ~AvlTree~ and ~AvlTreeNode~. 1 Includes */ #pragma once #include namespace RobustPlaneSweep { /* 1 Class ~AvlTreeNode~ */ template class AvlTreeNode { /* 1.1 Member variables */ private: TKey _key; int _height; int _balance; /* 1.1 ~SwapParentChildNode~ */ static void SwapParentChildNode(AvlTreeNode* parent, AvlTreeNode* child) { int heightTemp = parent->_height; parent->_height = child->_height; child->_height = heightTemp; int balanceTemp = parent->_balance; parent->_balance = child->_balance; child->_balance = balanceTemp; AvlTreeNode* childLeft = child->Left; AvlTreeNode* childRight = child->Right; AvlTreeNode* parentLeft = parent->Left; AvlTreeNode* parentRight = parent->Right; parent->Left = childLeft; parent->Right = childRight; child->Left = (parentLeft == child ? parent : parentLeft); child->Right = (parentRight == child ? parent : parentRight); AvlTreeNode* parentTemp = parent->Parent; parent->Parent = child->Parent; child->Parent = parentTemp; if (parent->Left != NULL) { parent->Left->Parent = parent; } if (parent->Right != NULL) { parent->Right->Parent = parent; } if (child->Left != NULL) { child->Left->Parent = child; } if (child->Right != NULL) { child->Right->Parent = child; } if (child->Parent != NULL) { if (child->Parent->Left == parent) { child->Parent->Left = child; } else if (child->Parent->Right == parent) { child->Parent->Right = child; } else { throw new std::invalid_argument("child"); } } } public: /* 1.1 Public member variables */ TValue Value; AvlTreeNode* Left; AvlTreeNode* Right; AvlTreeNode* Parent; /* 1.1 ~GetKey~ */ TKey GetKey() const { return _key; } /* 1.1 ~SetKey~ */ void SetKey(const TKey &key) { _key = key; } /* 1.1 ~GetHeight~ */ int GetHeight() const { return _height; } /* 1.1 ~GetBalance~ */ int GetBalance() const { return _balance; } /* 1.1 Constructor */ explicit AvlTreeNode(const TKey &key) : _key(key), _height(1), _balance(0), Value(NULL), Left(NULL), Right(NULL), Parent(NULL) { } /* 1.1 Destructor */ ~AvlTreeNode() { if (Left != NULL) { delete Left; Left = NULL; } if (Right != NULL) { delete Right; Right = NULL; } } /* 1.1 ~SwapNodes~ This method swaps two nodes in the AVL tree. There are no validity checks. The caller has to know what he/she is doing. */ static void SwapNodes(AvlTreeNode* x, AvlTreeNode* y) { if (x->Parent == y) { SwapParentChildNode(y, x); } else if (y->Parent == x) { SwapParentChildNode(x, y); } else { int heightTemp = x->_height; x->_height = y->_height; y->_height = heightTemp; int balanceTemp = x->_balance; x->_balance = y->_balance; y->_balance = balanceTemp; AvlTreeNode* leftTemp = x->Left; x->Left = y->Left; y->Left = leftTemp; AvlTreeNode* rightTemp = x->Right; x->Right = y->Right; y->Right = rightTemp; AvlTreeNode* parentTemp = x->Parent; x->Parent = y->Parent; y->Parent = parentTemp; if (x->Left != NULL) { x->Left->Parent = x; } if (x->Right != NULL) { x->Right->Parent = x; } if (y->Left != NULL) { y->Left->Parent = y; } if (y->Right != NULL) { y->Right->Parent = y; } if (x->Parent != NULL) { if (x->Parent->Left == y) { x->Parent->Left = x; } else if (x->Parent->Right == y) { x->Parent->Right = x; } else { throw new std::logic_error("tree inconsistent"); } } if (y->Parent != NULL) { if (y->Parent->Left == x) { y->Parent->Left = y; } else if (y->Parent->Right == x) { y->Parent->Right = y; } else { throw new std::logic_error("tree inconsistent"); } } } } /* 1.1 ~CalculateHeightAndBalance~ */ static void CalculateHeightAndBalance(AvlTreeNode *node) { while (node != NULL) { int height, balance; if (node->Left != NULL) { height = node->Left->GetHeight(); if (node->Right != NULL) { int temp = node->Right->GetHeight(); balance = height - temp; if (temp > height) { height = temp; } } else { balance = height; } } else if (node->Right != NULL) { height = node->Right->GetHeight(); balance = -height; } else { height = balance = 0; } ++height; if (node->GetHeight() != height || node->GetBalance() != balance) { node->_height = height; node->_balance = balance; node = node->Parent; } else { node = NULL; } } } /* 1.1 ~GetNext~ */ AvlTreeNode* GetNext() { AvlTreeNode* node; if (Right != NULL) { node = Right; while (node->Left != NULL) { node = node->Left; } return node; } AvlTreeNode* lastNode = this; node = Parent; while (node != NULL && node->Right == lastNode) { lastNode = node; node = node->Parent; } return node; } /* 1.1 ~GetPrevious~ */ AvlTreeNode* GetPrevious() { AvlTreeNode* node; if (Left != NULL) { node = Left; while (node->Right != NULL) { node = node->Right; } return node; } AvlTreeNode* lastNode = this; node = Parent; while (node != NULL && node->Left == lastNode) { lastNode = node; node = node->Parent; } return node; } }; /* 1 Class ~AvlTree~ */ template class AvlTree { private: /* 1.1 Private enum ~Direction~ */ enum class Direction { Undefined, Left, Right }; /* 1.1 Member variables */ AvlTreeNode* _root; int _count; Comparision* _comparisonObject; /* 1.1 ~FindNode~ */ bool FindNode(const TKey& key, AvlTreeNode*& node, AvlTreeNode*& parentNode, Direction& parentNodeDirection) const { AvlTreeNode* currentNode = _root; AvlTreeNode* lastNode = NULL; Direction lastNodeDirection = Direction::Undefined; for (;;) { if (currentNode == NULL) { node = NULL; parentNode = lastNode; parentNodeDirection = lastNodeDirection; return false; } int compareResult = _comparisonObject->Compare(key, currentNode->GetKey()); if (compareResult < 0) { lastNode = currentNode; lastNodeDirection = Direction::Left; currentNode = currentNode->Left; } else if (compareResult > 0) { lastNode = currentNode; lastNodeDirection = Direction::Right; currentNode = currentNode->Right; } else { node = currentNode; parentNode = lastNode; parentNodeDirection = lastNodeDirection; return true; } } } /* 1.1 ~Rebalance~ */ void Rebalance(AvlTreeNode* node) { AvlTreeNode* currentNode = node; while (currentNode != NULL) { AvlTreeNode* parentNode = currentNode->Parent; if (currentNode->GetBalance() < -1) { if (currentNode->Right->GetBalance() <= 0) { /* rotation left * A * \ B * B -> / \ * \ A C * C * */ Rotate(parentNode, currentNode, currentNode->Right, Direction::Left); } else { /* rotation right + rotation left * A A * \ \ B * C -> B -> / \ * / \ A C * B C * */ Rotate(currentNode, currentNode->Right, currentNode->Right->Left, Direction::Right); Rotate(parentNode, currentNode, currentNode->Right, Direction::Left); } } else if (currentNode->GetBalance() > 1) { if (currentNode->Left->GetBalance() >= 0) { /* rotation right * C * / B * B -> / \ * / A C * A * */ Rotate(parentNode, currentNode, currentNode->Left, Direction::Right); } else { /* rotation left + rotation right * C C * / / B * A -> B -> / \ * \ / A C * B A * */ Rotate(currentNode, currentNode->Left, currentNode->Left->Right, Direction::Left); Rotate(parentNode, currentNode, currentNode->Left, Direction::Right); } } currentNode = parentNode; } } /* 1.1 ~Rotate~ */ void Rotate(AvlTreeNode* parentNode, AvlTreeNode* rootNode, AvlTreeNode* pivotNode, Direction direction) { AvlTreeNode* temp; pivotNode->Parent = parentNode; if (direction == Direction::Right) { temp = pivotNode->Right; pivotNode->Right = rootNode; rootNode->Left = temp; } else { temp = pivotNode->Left; pivotNode->Left = rootNode; rootNode->Right = temp; } rootNode->Parent = pivotNode; if (temp != NULL) { temp->Parent = rootNode; } if (parentNode != NULL) { if (parentNode->Left == rootNode) { parentNode->Left = pivotNode; } else if (parentNode->Right == rootNode) { parentNode->Right = pivotNode; } else { throw new std::logic_error("rotation error"); } } else { _root = pivotNode; } AvlTreeNode::CalculateHeightAndBalance(rootNode); } public: /* 1.1 Constructor */ explicit AvlTree(Comparision* comparisonObject) { _root = NULL; _count = 0; _comparisonObject = comparisonObject; } /* 1.1 Destructor */ ~AvlTree() { if (_root != NULL) { delete _root; _root = NULL; } } /* 1.1 ~TryAddNode~ */ bool TryAddNode(const TKey& key, AvlTreeNode*& node) { AvlTreeNode* parentNode; Direction parentNodeDirection; if (!FindNode(key, node, parentNode, parentNodeDirection)) { node = new AvlTreeNode(key); ++_count; if (parentNode != NULL) { if (parentNodeDirection == Direction::Left) { parentNode->Left = node; node->Parent = parentNode; } else { parentNode->Right = node; node->Parent = parentNode; } AvlTreeNode::CalculateHeightAndBalance(parentNode); if (parentNode->Parent != NULL) { Rebalance(parentNode->Parent); } } else { _root = node; } return true; } else { return false; } } /* 1.1 ~Remove~ */ void Remove(AvlTreeNode* node) { AvlTreeNode* parentNode = node->Parent; if (node->Left == NULL || node->Right == NULL) { AvlTreeNode* newChild = (node->Left == NULL ? node->Right : node->Left); if (newChild != NULL) { newChild->Parent = parentNode; } if (node->Parent != NULL) { if (parentNode->Left == node) { parentNode->Left = newChild; } else if (parentNode->Right == node) { parentNode->Right = newChild; } else { throw new std::logic_error("tree inconsistent"); } AvlTreeNode::CalculateHeightAndBalance(parentNode); Rebalance(parentNode); } else { _root = newChild; } } else { if (node->Right->Left != NULL) { AvlTreeNode* nextGreaterNode = node->Right->Left; while (nextGreaterNode->Left != NULL) { nextGreaterNode = nextGreaterNode->Left; } AvlTreeNode* tempParent = nextGreaterNode->Parent; tempParent->Left = nextGreaterNode->Right; if (tempParent->Left != NULL) { tempParent->Left->Parent = tempParent; } if (parentNode != NULL) { if (parentNode->Left == node) { parentNode->Left = nextGreaterNode; } else if (parentNode->Right == node) { parentNode->Right = nextGreaterNode; } else { throw new std::logic_error("tree inconsistent"); } } else { _root = nextGreaterNode; } nextGreaterNode->Parent = node->Parent; nextGreaterNode->Left = node->Left; nextGreaterNode->Left->Parent = nextGreaterNode; nextGreaterNode->Right = node->Right; nextGreaterNode->Right->Parent = nextGreaterNode; AvlTreeNode::CalculateHeightAndBalance(tempParent); Rebalance(tempParent); AvlTreeNode::CalculateHeightAndBalance(nextGreaterNode); Rebalance(nextGreaterNode); } else { AvlTreeNode* nextGreaterNode = node->Right; nextGreaterNode->Left = node->Left; nextGreaterNode->Left->Parent = nextGreaterNode; if (parentNode != NULL) { if (parentNode->Left == node) { parentNode->Left = nextGreaterNode; } else if (parentNode->Right == node) { parentNode->Right = nextGreaterNode; } else { throw new std::logic_error("tree inconsistent"); } } else { _root = nextGreaterNode; } nextGreaterNode->Parent = node->Parent; AvlTreeNode::CalculateHeightAndBalance(nextGreaterNode); Rebalance(nextGreaterNode); } } node->Left = NULL; node->Right = NULL; delete node; --_count; } /* 1.1 ~GetRoot~ */ AvlTreeNode* GetRoot() const { return _root; } /* 1.1 ~SwapNodes~ */ void SwapNodes(AvlTreeNode* x, AvlTreeNode* y) { AvlTreeNode::SwapNodes(x, y); if (x == _root) { _root = y; } else if (y == _root) { _root = x; } } }; }