Files
2026-02-02 04:50:13 +01:00

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