forked from 0ad/0ad
212 lines
5.3 KiB
C++
212 lines
5.3 KiB
C++
#ifndef __TREE_H
|
|
#define __TREE_H
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Tree: template class to build a binary tree of elements of class T
|
|
template <class T,class Cmp>
|
|
class Tree
|
|
{
|
|
public:
|
|
template <class T>
|
|
class Node {
|
|
public:
|
|
Node<T>* _Next;
|
|
|
|
public:
|
|
Node() : _Left(0), _Right(0) {}
|
|
|
|
int _Index;
|
|
T _Element;
|
|
Node<T>* _Left;
|
|
Node<T>* _Right;
|
|
};
|
|
|
|
|
|
public:
|
|
Tree();
|
|
~Tree();
|
|
|
|
void Clear();
|
|
|
|
int Find(T& element);
|
|
int Find(Node<T>* _node,T& _vtx);
|
|
|
|
int Add(T& element);
|
|
int Add(Node<T>* _node,T& _vtx,int _index);
|
|
|
|
// total nodes currently in tree
|
|
int Entries() { return _Size; }
|
|
|
|
void Reserve(int count) { _AllocatedNodes.reserve(count); }
|
|
|
|
T& operator[](int index) { return _AllocatedNodes[index]->_Element; }
|
|
|
|
private:
|
|
// the root node of the tree
|
|
Node<T>* _Root;
|
|
// all allocated nodes in tree
|
|
std::vector<Node<T>*> _AllocatedNodes;
|
|
// size of tree
|
|
int _Size;
|
|
// the comparison function used to compare two elements in the tree
|
|
Cmp _Cmp;
|
|
};
|
|
|
|
//***************************************************************************
|
|
// Default Tree constructor - create tree with no allocated nodes
|
|
//***************************************************************************
|
|
template <class T,class Cmp>
|
|
Tree<T,Cmp>::Tree()
|
|
{
|
|
_Root=0;
|
|
_Size=0;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
// Tree destructor
|
|
//***************************************************************************
|
|
template <class T,class Cmp>
|
|
Tree<T,Cmp>::~Tree()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
|
|
template <class T,class Cmp>
|
|
void Tree<T,Cmp>::Clear()
|
|
{
|
|
for (int i=0;i<_AllocatedNodes.Entries();i++) {
|
|
_NodePile.Release(_AllocatedNodes[i]);
|
|
}
|
|
_AllocatedNodes.SetSize(0);
|
|
_Root=0;
|
|
_Size=0;
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Add : insert an element into the tree; return the index of the treenode
|
|
// at which the element was added, or, if an identical element was already
|
|
// in the tree, return it's index
|
|
//***************************************************************************
|
|
template <class T,class Cmp>
|
|
int Tree<T,Cmp>::Add(T& element)
|
|
{
|
|
if (_Root) {
|
|
int index=Add(_Root,element,_Size);
|
|
if (index==_Size) {
|
|
// element added to tree
|
|
_Size++;
|
|
} else {
|
|
// element not added
|
|
}
|
|
return index;
|
|
} else {
|
|
_Root=_NodePile.Allocate();
|
|
_AllocatedNodes.Add(_Root);
|
|
_Root->_Element=element;
|
|
_Root->_Index=0;
|
|
_Root->_Left=0;
|
|
_Root->_Right=0;
|
|
_Size++;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
// Add : insert an element into the given node; return the index of the
|
|
// treenode at which the element was added, or, if an identical element was
|
|
// already in the tree, return it's index
|
|
//***************************************************************************
|
|
template <class T,class Cmp>
|
|
int Tree<T,Cmp>::Add(Node<T>* _node,T& element,int _index)
|
|
{
|
|
// compare given element with element at given node
|
|
int cmp=_Cmp.compare(_node->_Element,element);
|
|
if (cmp==0) {
|
|
// identical - return index of this node
|
|
return _node->_Index;
|
|
} else {
|
|
if (cmp==-1) {
|
|
// this node less than new node
|
|
if (_node->_Left) {
|
|
// send down left tree
|
|
return Add(_node->_Left,element,_index);
|
|
} else {
|
|
// no left node - create one
|
|
_node->_Left=_NodePile.Allocate();
|
|
_AllocatedNodes.Add(_node->_Left);
|
|
_node->_Left->_Element=element;
|
|
_node->_Left->_Index=_index;
|
|
_node->_Left->_Left=0;
|
|
_node->_Left->_Right=0;
|
|
return _index;
|
|
}
|
|
} else {
|
|
// this node greater than new node
|
|
if (_node->_Right) {
|
|
// send down right tree
|
|
return Add(_node->_Right,element,_index);
|
|
} else {
|
|
// no right node - create one
|
|
_node->_Right=_NodePile.Allocate();
|
|
_AllocatedNodes.Add(_node->_Right);
|
|
_node->_Right->_Element=element;
|
|
_node->_Right->_Index=_index;
|
|
_node->_Right->_Left=0;
|
|
_node->_Right->_Right=0;
|
|
return _index;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
// Find: try and find a matching element in the tree; return the index of the
|
|
// treenode at which a match was found, or -1 if no match found
|
|
//***************************************************************************
|
|
template <class T,class Cmp>
|
|
int Tree<T,Cmp>::Find(T& element)
|
|
{
|
|
return _Root ? Find(_Root,element) : -1;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
// Find: try and find a matching element in the given node; return the index
|
|
// of the treenode at which a match was found, or -1 if no match found
|
|
//***************************************************************************
|
|
template <class T,class Cmp>
|
|
int Tree<T,Cmp>::Find(Node<T>* _node,T& element)
|
|
{
|
|
// compare given element with element at given node
|
|
int cmp=_Cmp.compare(_node->_Element,element);
|
|
if (cmp==0) {
|
|
// identical - return index of this node
|
|
return _node->_Index;
|
|
} else {
|
|
if (cmp==-1) {
|
|
// this node less than new node
|
|
if (_node->_Left) {
|
|
// send down left tree
|
|
return Find(_node->_Left,element);
|
|
} else {
|
|
// no left node - no match on this subtree
|
|
return -1;
|
|
}
|
|
} else {
|
|
// this node greater than new node
|
|
if (_node->_Right) {
|
|
// send down right tree
|
|
return Find(_node->_Right,element);
|
|
} else {
|
|
// no left node - no match on this subtree
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endif |