Files
secondo/Algebras/RobustPlaneSweep/Helper/AvlTree.h
2026-01-23 17:03:45 +08:00

760 lines
16 KiB
C++

/*
----
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 <stdexcept>
namespace RobustPlaneSweep
{
/*
1 Class ~AvlTreeNode~
*/
template<class TKey, class TValue>
class AvlTreeNode
{
/*
1.1 Member variables
*/
private:
TKey _key;
int _height;
int _balance;
/*
1.1 ~SwapParentChildNode~
*/
static void SwapParentChildNode(AvlTreeNode<TKey, TValue>* parent,
AvlTreeNode<TKey, TValue>* child)
{
int heightTemp = parent->_height;
parent->_height = child->_height;
child->_height = heightTemp;
int balanceTemp = parent->_balance;
parent->_balance = child->_balance;
child->_balance = balanceTemp;
AvlTreeNode<TKey, TValue>* childLeft = child->Left;
AvlTreeNode<TKey, TValue>* childRight = child->Right;
AvlTreeNode<TKey, TValue>* parentLeft = parent->Left;
AvlTreeNode<TKey, TValue>* parentRight = parent->Right;
parent->Left = childLeft;
parent->Right = childRight;
child->Left = (parentLeft == child ? parent : parentLeft);
child->Right = (parentRight == child ? parent : parentRight);
AvlTreeNode<TKey, TValue>* 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<TKey, TValue>* Left;
AvlTreeNode<TKey, TValue>* Right;
AvlTreeNode<TKey, TValue>* 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<TKey, TValue>* x,
AvlTreeNode<TKey, TValue>* 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<TKey, TValue>* leftTemp = x->Left;
x->Left = y->Left;
y->Left = leftTemp;
AvlTreeNode<TKey, TValue>* rightTemp = x->Right;
x->Right = y->Right;
y->Right = rightTemp;
AvlTreeNode<TKey, TValue>* 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<TKey, TValue> *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<TKey, TValue>* GetNext()
{
AvlTreeNode<TKey, TValue>* node;
if (Right != NULL) {
node = Right;
while (node->Left != NULL) {
node = node->Left;
}
return node;
}
AvlTreeNode<TKey, TValue>* lastNode = this;
node = Parent;
while (node != NULL && node->Right == lastNode) {
lastNode = node;
node = node->Parent;
}
return node;
}
/*
1.1 ~GetPrevious~
*/
AvlTreeNode<TKey, TValue>* GetPrevious()
{
AvlTreeNode<TKey, TValue>* node;
if (Left != NULL) {
node = Left;
while (node->Right != NULL) {
node = node->Right;
}
return node;
}
AvlTreeNode<TKey, TValue>* lastNode = this;
node = Parent;
while (node != NULL && node->Left == lastNode) {
lastNode = node;
node = node->Parent;
}
return node;
}
};
/*
1 Class ~AvlTree~
*/
template<class TKey, class TValue, typename Comparision>
class AvlTree
{
private:
/*
1.1 Private enum ~Direction~
*/
enum class Direction
{
Undefined,
Left,
Right
};
/*
1.1 Member variables
*/
AvlTreeNode<TKey, TValue>* _root;
int _count;
Comparision* _comparisonObject;
/*
1.1 ~FindNode~
*/
bool FindNode(const TKey& key,
AvlTreeNode<TKey, TValue>*& node,
AvlTreeNode<TKey, TValue>*& parentNode,
Direction& parentNodeDirection) const
{
AvlTreeNode<TKey, TValue>* currentNode = _root;
AvlTreeNode<TKey, TValue>* 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<TKey, TValue>* node)
{
AvlTreeNode<TKey, TValue>* currentNode = node;
while (currentNode != NULL) {
AvlTreeNode<TKey, TValue>* 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<TKey, TValue>* parentNode,
AvlTreeNode<TKey, TValue>* rootNode,
AvlTreeNode<TKey, TValue>* pivotNode,
Direction direction)
{
AvlTreeNode<TKey, TValue>* 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<TKey, TValue>::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<TKey, TValue>*& node)
{
AvlTreeNode<TKey, TValue>* parentNode;
Direction parentNodeDirection;
if (!FindNode(key, node, parentNode, parentNodeDirection)) {
node = new AvlTreeNode<TKey, TValue>(key);
++_count;
if (parentNode != NULL) {
if (parentNodeDirection == Direction::Left) {
parentNode->Left = node;
node->Parent = parentNode;
} else {
parentNode->Right = node;
node->Parent = parentNode;
}
AvlTreeNode<TKey, TValue>::CalculateHeightAndBalance(parentNode);
if (parentNode->Parent != NULL) {
Rebalance(parentNode->Parent);
}
} else {
_root = node;
}
return true;
} else {
return false;
}
}
/*
1.1 ~Remove~
*/
void Remove(AvlTreeNode<TKey, TValue>* node)
{
AvlTreeNode<TKey, TValue>* parentNode = node->Parent;
if (node->Left == NULL || node->Right == NULL) {
AvlTreeNode<TKey, TValue>* 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<TKey, TValue>::CalculateHeightAndBalance(parentNode);
Rebalance(parentNode);
} else {
_root = newChild;
}
} else {
if (node->Right->Left != NULL) {
AvlTreeNode<TKey, TValue>* nextGreaterNode = node->Right->Left;
while (nextGreaterNode->Left != NULL) {
nextGreaterNode = nextGreaterNode->Left;
}
AvlTreeNode<TKey, TValue>* 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<TKey, TValue>::CalculateHeightAndBalance(tempParent);
Rebalance(tempParent);
AvlTreeNode<TKey, TValue>::CalculateHeightAndBalance(nextGreaterNode);
Rebalance(nextGreaterNode);
} else {
AvlTreeNode<TKey, TValue>* 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<TKey, TValue>::CalculateHeightAndBalance(nextGreaterNode);
Rebalance(nextGreaterNode);
}
}
node->Left = NULL;
node->Right = NULL;
delete node;
--_count;
}
/*
1.1 ~GetRoot~
*/
AvlTreeNode<TKey, TValue>* GetRoot() const
{
return _root;
}
/*
1.1 ~SwapNodes~
*/
void SwapNodes(AvlTreeNode<TKey, TValue>* x, AvlTreeNode<TKey, TValue>* y)
{
AvlTreeNode<TKey, TValue>::SwapNodes(x, y);
if (x == _root) {
_root = y;
} else if (y == _root) {
_root = x;
}
}
};
}