mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-15 21:26:57 +00:00
1
This commit is contained in:
+316
@@ -0,0 +1,316 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
#ifndef __TREE_H__
|
||||
#define __TREE_H__
|
||||
|
||||
#include "List.h"
|
||||
#include "ArrayStack.h"
|
||||
|
||||
// NTreeNode: Class decleration and definition
|
||||
template <class T> class NTreeNode
|
||||
{
|
||||
public:
|
||||
// constructor
|
||||
NTreeNode<T>( T data );
|
||||
|
||||
NTreeNode<T> *PrependChild( NTreeNode<T> *node );
|
||||
NTreeNode<T> *AppendChild( NTreeNode<T> *node );
|
||||
NTreeNode<T> *InsertChildAfterIndex( NTreeNode<T> *node, int index );
|
||||
NTreeNode<T> *InsertChildBeforeIndex( NTreeNode<T> *node, int index );
|
||||
NTreeNode<T> *RemoveChild( Position position );
|
||||
NTreeNode<T> *RemoveChild( int index );
|
||||
Position InsertAfter( NTreeNode<T> *node, Position position );
|
||||
Position InsertBefore( NTreeNode<T> *node, Position position );
|
||||
int GetNumChildren();
|
||||
Position GetChildPosition( int childNum );
|
||||
NTreeNode<T> *GetChild( int childNum );
|
||||
NTreeNode<T> *GetChild( Position position );
|
||||
int GetIndexRelativeToParent();
|
||||
T GetItem();
|
||||
NTreeNode<T> *GetParent();
|
||||
NTreeNode<T> *GetRoot();
|
||||
NTreeNode<T> *GetNextSibling();
|
||||
void Traverse( void (*VisitFunc)( T, int depth ), int maxTreeDepth );
|
||||
NTreeNode<T> *ReentrantTraversalGetFirst( int maxTreeDepth );
|
||||
NTreeNode<T> *ReentrantTraversalGetNext( void );
|
||||
|
||||
protected:
|
||||
GList<NTreeNode<T> * > *list;
|
||||
T data;
|
||||
NTreeNode<T> *parent;
|
||||
ArrayStack<NTreeNode<T> *> *reentrantStack;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T>::NTreeNode( T data )
|
||||
{
|
||||
list = new GList<NTreeNode<T> * >;
|
||||
this->data = data;
|
||||
this->parent = NULL;
|
||||
this->reentrantStack = NULL;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::PrependChild( NTreeNode<T> *node )
|
||||
{
|
||||
node->parent = this;
|
||||
return list->GetItemAtPosition( list->InsertAtHead( node ) );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::AppendChild( NTreeNode<T> *node )
|
||||
{
|
||||
node->parent = this;
|
||||
return list->GetItemAtPosition( list->InsertAtTail( node ) );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::InsertChildAfterIndex( NTreeNode<T> *node, int index )
|
||||
{
|
||||
node->parent = this;
|
||||
if( index < 0 )
|
||||
{
|
||||
// if out of range in the negative direction, prepend
|
||||
this->PrependChild( node );
|
||||
}
|
||||
else if( index > list->GetNumItems() - 1 )
|
||||
{
|
||||
// if out of range, just append.
|
||||
this->AppendChild( node );
|
||||
}
|
||||
else
|
||||
{
|
||||
Position pos;
|
||||
pos = list->GetPositionAtIndex( index );
|
||||
list->InsertAfter( node, pos );
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::InsertChildBeforeIndex( NTreeNode<T> *node, int index )
|
||||
{
|
||||
node->parent = this;
|
||||
if( index < 0 )
|
||||
{
|
||||
// if out of range in the negative direction, prepend
|
||||
this->PrependChild( node );
|
||||
}
|
||||
else if( index > list->GetNumItems() - 1 )
|
||||
{
|
||||
// if out of range, just append.
|
||||
this->AppendChild( node );
|
||||
}
|
||||
else
|
||||
{
|
||||
Position pos;
|
||||
pos = list->GetPositionAtIndex( index );
|
||||
list->InsertBefore( node, pos );
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::RemoveChild( Position position )
|
||||
{
|
||||
NTreeNode<T> **node = ( NTreeNode<T> ** )( void * )position;
|
||||
( *node )->parent = NULL;
|
||||
return list->Remove( position );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::RemoveChild( int index )
|
||||
{
|
||||
Position position = list->GetPositionAtIndex( index );
|
||||
NTreeNode<T> **node = ( NTreeNode<T> ** )( void * )position;
|
||||
( *node )->parent = NULL;
|
||||
return list->Remove( position );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Position NTreeNode<T>::InsertAfter( NTreeNode<T> *node, Position position )
|
||||
{
|
||||
node->parent = this;
|
||||
return list->InsertAfter( node, position );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Position NTreeNode<T>::InsertBefore( NTreeNode<T> *node, Position position )
|
||||
{
|
||||
node->parent = this;
|
||||
return list->InsertBefore( node, position );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int NTreeNode<T>::GetNumChildren()
|
||||
{
|
||||
return list->GetNumItems();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Position NTreeNode<T>::GetChildPosition( int childNum )
|
||||
{
|
||||
return list->GetPositionAtIndex( childNum );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::GetChild( int childNum )
|
||||
{
|
||||
return list->GetItemAtIndex( childNum );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::GetChild( Position position )
|
||||
{
|
||||
return list->GetItemAtIndex( position );
|
||||
}
|
||||
|
||||
template <class T>
|
||||
int NTreeNode<T>::GetIndexRelativeToParent()
|
||||
{
|
||||
if( !parent )
|
||||
{
|
||||
assert( 0 ); // hack
|
||||
return -1;
|
||||
}
|
||||
GListIterator<NTreeNode<T> *> iterator( parent->list );
|
||||
int i;
|
||||
for( i = 0, iterator.GotoHead(); !iterator.AtEnd(); iterator++, i++ )
|
||||
{
|
||||
if( iterator.GetCurrent() == this )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
assert( 0 ); // hack
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T NTreeNode<T>::GetItem()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::GetParent()
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::GetRoot()
|
||||
{
|
||||
NTreeNode<T> *node;
|
||||
node = this;
|
||||
while( node->GetParent() )
|
||||
{
|
||||
node = node->GetParent();
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::GetNextSibling()
|
||||
{
|
||||
int currentID, siblingID;
|
||||
NTreeNode<T> *parent;
|
||||
parent = this->GetParent();
|
||||
if( !parent )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
currentID = this->GetIndexRelativeToParent();
|
||||
siblingID = currentID + 1;
|
||||
if( siblingID < parent->GetNumChildren() )
|
||||
{
|
||||
return parent->GetChild( siblingID );
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void NTreeNode<T>::Traverse( void (*VisitFunc)( T, int depth ), int maxTreeDepth )
|
||||
{
|
||||
ArrayStack<NTreeNode<T> *> stack( maxTreeDepth );
|
||||
NTreeNode<T> *current, *nextSibling;
|
||||
|
||||
stack.Push( this );
|
||||
Visit( this->GetItem(), 0 );
|
||||
while( !stack.IsEmpty() )
|
||||
{
|
||||
current = stack.Pop();
|
||||
if( current->GetNumChildren() > 0 )
|
||||
{
|
||||
stack.Push( current );
|
||||
stack.Push( current->GetChild( 0 ) );
|
||||
Visit( current->GetChild( 0 )->GetItem(), stack.GetDepth() - 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
while( !stack.IsEmpty() && !( nextSibling = current->GetNextSibling() ) )
|
||||
{
|
||||
current = stack.Pop();
|
||||
}
|
||||
if( !stack.IsEmpty() )
|
||||
{
|
||||
stack.Push( nextSibling );
|
||||
Visit( nextSibling->GetItem(), stack.GetDepth() - 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::ReentrantTraversalGetFirst( int maxTreeDepth )
|
||||
{
|
||||
if( reentrantStack )
|
||||
{
|
||||
delete reentrantStack;
|
||||
}
|
||||
reentrantStack = new ArrayStack<NTreeNode<T> *>( maxTreeDepth );
|
||||
reentrantStack->Push( this );
|
||||
return this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
NTreeNode<T> *NTreeNode<T>::ReentrantTraversalGetNext( void )
|
||||
{
|
||||
NTreeNode<T> *current, *nextSibling;
|
||||
|
||||
while( !reentrantStack->IsEmpty() )
|
||||
{
|
||||
current = reentrantStack->Pop();
|
||||
if( current->GetNumChildren() > 0 )
|
||||
{
|
||||
reentrantStack->Push( current );
|
||||
reentrantStack->Push( current->GetChild( 0 ) );
|
||||
return current->GetChild( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
while( !reentrantStack->IsEmpty() && !( nextSibling = current->GetNextSibling() ) )
|
||||
{
|
||||
current = reentrantStack->Pop();
|
||||
}
|
||||
if( !reentrantStack->IsEmpty() )
|
||||
{
|
||||
reentrantStack->Push( nextSibling );
|
||||
return nextSibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete reentrantStack;
|
||||
reentrantStack = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* __TREE_H__ */
|
||||
Reference in New Issue
Block a user