232 lines
5.0 KiB
C++
232 lines
5.0 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program 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 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2006-2010 - Frictional Games
|
|
*
|
|
* This file is part of HPL1 Engine.
|
|
*/
|
|
|
|
#ifndef HPL_BINTREE_H
|
|
#define HPL_BINTREE_H
|
|
|
|
#include "common/list.h"
|
|
|
|
namespace hpl {
|
|
|
|
enum eBinTreeNode {
|
|
eBinTreeNode_Left,
|
|
eBinTreeNode_Right
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// TREE NODE CLASS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template<class T>
|
|
class BinTreeNode {
|
|
public:
|
|
T *GetData() {
|
|
return &mData;
|
|
}
|
|
|
|
BinTreeNode(T aData, BinTreeNode<T> *aParent, eBinTreeNode aParentDir) {
|
|
for (int i = 0; i < 2; i++)
|
|
mChild[i] = NULL;
|
|
mData = aData;
|
|
mParent = aParent;
|
|
mParentDir = aParentDir;
|
|
}
|
|
|
|
BinTreeNode<T> *AddChild(eBinTreeNode i, T aData) {
|
|
if (mChild[i] == NULL) {
|
|
mChild[i] = hplNew(BinTreeNode<T>, (aData, this, i));
|
|
return mChild[i];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
BinTreeNode<T> *GetChild(eBinTreeNode i) {
|
|
return mChild[i];
|
|
}
|
|
|
|
BinTreeNode<T> *GetParent() {
|
|
return mParent;
|
|
}
|
|
|
|
private:
|
|
BinTreeNode<T> *mChild[2];
|
|
BinTreeNode<T> *mParent;
|
|
T mData;
|
|
eBinTreeNode mParentDir;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// MAIN TREE CLASS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template<class T>
|
|
class BinTree {
|
|
public:
|
|
BinTree() {
|
|
mlNumOfNodes = 0;
|
|
mFirstNode = NULL;
|
|
}
|
|
|
|
~BinTree() {
|
|
Clear();
|
|
}
|
|
|
|
/**
|
|
* Clears the entire tree
|
|
* \return number of nodes deleted
|
|
*/
|
|
int Clear() {
|
|
mlNum = 0;
|
|
DeleteNode(mFirstNode);
|
|
mFirstNode = NULL;
|
|
return mlNum;
|
|
}
|
|
|
|
/**
|
|
* Insert a node to the tree.
|
|
* \todo only works to set the root node.
|
|
* \param aData the data to insert
|
|
* \return
|
|
*/
|
|
BinTreeNode<T> *Insert(T aData) {
|
|
if (mFirstNode == NULL) {
|
|
mFirstNode = hplNew(BinTreeNode<T>, (aData, NULL, eBinTreeNode_Left));
|
|
mlNumOfNodes++;
|
|
|
|
return mFirstNode;
|
|
}
|
|
|
|
// Insertion other then at the root is not supported!
|
|
BinTreeNode<T> *Node = mFirstNode;
|
|
eBinTreeNode c;
|
|
while (true) {
|
|
// if(Node->GetData()<aData)
|
|
c = eBinTreeNode_Left;
|
|
// else
|
|
// c = eBinTreeNode_Right;
|
|
|
|
if (Node->GetChild(c) == NULL) {
|
|
Node = Node->AddChild(c, aData);
|
|
break;
|
|
} else {
|
|
Node = Node->GetChild(c);
|
|
}
|
|
}
|
|
mlNumOfNodes++;
|
|
|
|
return Node;
|
|
}
|
|
|
|
/**
|
|
* Insert a node into a certain node in the tree
|
|
* \param aData the data to insert
|
|
* \param aNode the node to insert the data in
|
|
* \param aChild what child to insert at
|
|
* \return
|
|
*/
|
|
BinTreeNode<T> *InsertAt(T aData, BinTreeNode<T> *aNode, eBinTreeNode aChild = eBinTreeNode_Left) {
|
|
if (aNode == NULL)
|
|
return NULL;
|
|
|
|
if (aNode->GetChild(aChild) != NULL) {
|
|
aChild = aChild == eBinTreeNode_Left ? eBinTreeNode_Right : eBinTreeNode_Left;
|
|
if (aNode->GetChild(aChild) != NULL)
|
|
return NULL;
|
|
}
|
|
|
|
return aNode->AddChild(aChild, aData);
|
|
}
|
|
|
|
/**
|
|
* Get the size of the tree
|
|
* \return
|
|
*/
|
|
int Size() {
|
|
return mlNumOfNodes;
|
|
}
|
|
|
|
const Common::List<BinTreeNode<T> *> &GetLeafList() {
|
|
mlstNodes.clear();
|
|
PopulateLeafList(mFirstNode);
|
|
return mlstNodes;
|
|
}
|
|
|
|
/**
|
|
* Get a list of all the nodes in the tree
|
|
* \return
|
|
*/
|
|
const Common::List<BinTreeNode<T> *> &GetNodeList() {
|
|
mlstNodes.clear();
|
|
PopulateNodeList(mFirstNode);
|
|
return mlstNodes;
|
|
}
|
|
|
|
private:
|
|
int mlNumOfNodes;
|
|
BinTreeNode<T> *mFirstNode;
|
|
int mlNum;
|
|
|
|
Common::List<BinTreeNode<T> *> mlstNodes;
|
|
|
|
void DeleteNode(BinTreeNode<T> *aNode) {
|
|
if (aNode == NULL)
|
|
return;
|
|
|
|
DeleteNode(aNode->GetChild(eBinTreeNode_Left));
|
|
DeleteNode(aNode->GetChild(eBinTreeNode_Right));
|
|
|
|
hplDelete(aNode);
|
|
mlNum++;
|
|
}
|
|
|
|
void PopulateNodeList(BinTreeNode<T> *aNode) {
|
|
if (aNode == NULL)
|
|
return;
|
|
|
|
PopulateNodeList(aNode->GetChild(eBinTreeNode_Left));
|
|
mlstNodes.push_back(aNode);
|
|
PopulateNodeList(aNode->GetChild(eBinTreeNode_Right));
|
|
}
|
|
|
|
void PopulateLeafList(BinTreeNode<T> *aNode) {
|
|
if (aNode == NULL)
|
|
return;
|
|
|
|
if (aNode->GetChild(eBinTreeNode_Left) == NULL &&
|
|
aNode->GetChild(eBinTreeNode_Right) == NULL) {
|
|
mlstNodes.push_back(aNode);
|
|
}
|
|
|
|
PopulateLeafList(aNode->GetChild(eBinTreeNode_Left));
|
|
PopulateLeafList(aNode->GetChild(eBinTreeNode_Right));
|
|
}
|
|
};
|
|
|
|
} // namespace hpl
|
|
|
|
#endif // HPL_BINTREE_H
|