/* 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 .
*
*/
/*
* 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 BinTreeNode {
public:
T *GetData() {
return &mData;
}
BinTreeNode(T aData, BinTreeNode *aParent, eBinTreeNode aParentDir) {
for (int i = 0; i < 2; i++)
mChild[i] = NULL;
mData = aData;
mParent = aParent;
mParentDir = aParentDir;
}
BinTreeNode *AddChild(eBinTreeNode i, T aData) {
if (mChild[i] == NULL) {
mChild[i] = hplNew(BinTreeNode, (aData, this, i));
return mChild[i];
}
return NULL;
}
BinTreeNode *GetChild(eBinTreeNode i) {
return mChild[i];
}
BinTreeNode *GetParent() {
return mParent;
}
private:
BinTreeNode *mChild[2];
BinTreeNode *mParent;
T mData;
eBinTreeNode mParentDir;
};
//////////////////////////////////////////////////////////////////////////
// MAIN TREE CLASS
//////////////////////////////////////////////////////////////////////////
template
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 *Insert(T aData) {
if (mFirstNode == NULL) {
mFirstNode = hplNew(BinTreeNode, (aData, NULL, eBinTreeNode_Left));
mlNumOfNodes++;
return mFirstNode;
}
// Insertion other then at the root is not supported!
BinTreeNode *Node = mFirstNode;
eBinTreeNode c;
while (true) {
// if(Node->GetData()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 *InsertAt(T aData, BinTreeNode *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 *> &GetLeafList() {
mlstNodes.clear();
PopulateLeafList(mFirstNode);
return mlstNodes;
}
/**
* Get a list of all the nodes in the tree
* \return
*/
const Common::List *> &GetNodeList() {
mlstNodes.clear();
PopulateNodeList(mFirstNode);
return mlstNodes;
}
private:
int mlNumOfNodes;
BinTreeNode *mFirstNode;
int mlNum;
Common::List *> mlstNodes;
void DeleteNode(BinTreeNode *aNode) {
if (aNode == NULL)
return;
DeleteNode(aNode->GetChild(eBinTreeNode_Left));
DeleteNode(aNode->GetChild(eBinTreeNode_Right));
hplDelete(aNode);
mlNum++;
}
void PopulateNodeList(BinTreeNode *aNode) {
if (aNode == NULL)
return;
PopulateNodeList(aNode->GetChild(eBinTreeNode_Left));
mlstNodes.push_back(aNode);
PopulateNodeList(aNode->GetChild(eBinTreeNode_Right));
}
void PopulateLeafList(BinTreeNode *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