2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code 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 .
Doom 3 BFG Edition Source Code 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 Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# ifndef __BTREE_H__
# define __BTREE_H__
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Balanced Search Tree
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
//#define BTREE_CHECK
template < class objType , class keyType >
2012-11-28 15:47:07 +00:00
class idBTreeNode
{
2012-11-26 18:58:24 +00:00
public :
keyType key ; // key used for sorting
2012-11-28 15:47:07 +00:00
objType * object ; // if != NULL pointer to object stored in leaf node
idBTreeNode * parent ; // parent node
idBTreeNode * next ; // next sibling
idBTreeNode * prev ; // prev sibling
2012-11-26 18:58:24 +00:00
int numChildren ; // number of children
2012-11-28 15:47:07 +00:00
idBTreeNode * firstChild ; // first child
idBTreeNode * lastChild ; // last child
2012-11-26 18:58:24 +00:00
} ;
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
class idBTree
{
2012-11-26 18:58:24 +00:00
public :
2012-11-28 15:47:07 +00:00
idBTree ( ) ;
~ idBTree ( ) ;
2012-11-26 18:58:24 +00:00
void Init ( ) ;
void Shutdown ( ) ;
2012-11-28 15:47:07 +00:00
idBTreeNode < objType , keyType > * Add ( objType * object , keyType key ) ; // add an object to the tree
void Remove ( idBTreeNode < objType , keyType > * node ) ; // remove an object node from the tree
idBTreeNode < objType , keyType > * NodeFind ( keyType key ) const ; // find an object using the given key
idBTreeNode < objType , keyType > * NodeFindSmallestLargerEqual ( keyType key ) const ; // find an object with the smallest key larger equal the given key
idBTreeNode < objType , keyType > * NodeFindLargestSmallerEqual ( keyType key ) const ; // find an object with the largest key smaller equal the given key
objType * Find ( keyType key ) const ; // find an object using the given key
objType * FindSmallestLargerEqual ( keyType key ) const ; // find an object with the smallest key larger equal the given key
objType * FindLargestSmallerEqual ( keyType key ) const ; // find an object with the largest key smaller equal the given key
idBTreeNode < objType , keyType > * GetRoot ( ) const ; // returns the root node of the tree
2012-11-26 18:58:24 +00:00
int GetNodeCount ( ) const ; // returns the total number of nodes in the tree
2012-11-28 15:47:07 +00:00
idBTreeNode < objType , keyType > * GetNext ( idBTreeNode < objType , keyType > * node ) const ; // goes through all nodes of the tree
idBTreeNode < objType , keyType > * GetNextLeaf ( idBTreeNode < objType , keyType > * node ) const ; // goes through all leaf nodes of the tree
2012-11-26 18:58:24 +00:00
private :
2012-11-28 15:47:07 +00:00
idBTreeNode < objType , keyType > * root ;
idBlockAlloc < idBTreeNode < objType , keyType > , 128 > nodeAllocator ;
idBTreeNode < objType , keyType > * AllocNode ( ) ;
void FreeNode ( idBTreeNode < objType , keyType > * node ) ;
void SplitNode ( idBTreeNode < objType , keyType > * node ) ;
idBTreeNode < objType , keyType > * MergeNodes ( idBTreeNode < objType , keyType > * node1 , idBTreeNode < objType , keyType > * node2 ) ;
void CheckTree_r ( idBTreeNode < objType , keyType > * node , int & numNodes ) const ;
2012-11-26 18:58:24 +00:00
void CheckTree ( ) const ;
} ;
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE idBTree < objType , keyType , maxChildrenPerNode > : : idBTree ( )
{
2012-11-26 18:58:24 +00:00
assert ( maxChildrenPerNode > = 4 ) ;
root = NULL ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE idBTree < objType , keyType , maxChildrenPerNode > : : ~ idBTree ( )
{
2012-11-26 18:58:24 +00:00
Shutdown ( ) ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE void idBTree < objType , keyType , maxChildrenPerNode > : : Init ( )
{
2012-11-26 18:58:24 +00:00
root = AllocNode ( ) ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE void idBTree < objType , keyType , maxChildrenPerNode > : : Shutdown ( )
{
2012-11-26 18:58:24 +00:00
nodeAllocator . Shutdown ( ) ;
root = NULL ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE idBTreeNode < objType , keyType > * idBTree < objType , keyType , maxChildrenPerNode > : : Add ( objType * object , keyType key )
{
idBTreeNode < objType , keyType > * node , * child , * newNode ;
if ( root = = NULL )
{
2012-11-26 18:58:24 +00:00
root = AllocNode ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( root - > numChildren > = maxChildrenPerNode )
{
2012-11-26 18:58:24 +00:00
newNode = AllocNode ( ) ;
newNode - > key = root - > key ;
newNode - > firstChild = root ;
newNode - > lastChild = root ;
newNode - > numChildren = 1 ;
root - > parent = newNode ;
SplitNode ( root ) ;
root = newNode ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
newNode = AllocNode ( ) ;
newNode - > key = key ;
newNode - > object = object ;
2012-11-28 15:47:07 +00:00
for ( node = root ; node - > firstChild ! = NULL ; node = child )
{
if ( key > node - > key )
{
2012-11-26 18:58:24 +00:00
node - > key = key ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// find the first child with a key larger equal to the key of the new node
2012-11-28 15:47:07 +00:00
for ( child = node - > firstChild ; child - > next ; child = child - > next )
{
if ( key < = child - > key )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( child - > object )
{
if ( key < = child - > key )
{
2012-11-26 18:58:24 +00:00
// insert new node before child
2012-11-28 15:47:07 +00:00
if ( child - > prev )
{
2012-11-26 18:58:24 +00:00
child - > prev - > next = newNode ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
node - > firstChild = newNode ;
}
newNode - > prev = child - > prev ;
newNode - > next = child ;
child - > prev = newNode ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// insert new node after child
2012-11-28 15:47:07 +00:00
if ( child - > next )
{
2012-11-26 18:58:24 +00:00
child - > next - > prev = newNode ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
node - > lastChild = newNode ;
}
newNode - > prev = child ;
newNode - > next = child - > next ;
child - > next = newNode ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
newNode - > parent = node ;
node - > numChildren + + ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# ifdef BTREE_CHECK
CheckTree ( ) ;
# endif
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return newNode ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure the child has room to store another node
2012-11-28 15:47:07 +00:00
if ( child - > numChildren > = maxChildrenPerNode )
{
2012-11-26 18:58:24 +00:00
SplitNode ( child ) ;
2012-11-28 15:47:07 +00:00
if ( key < = child - > prev - > key )
{
2012-11-26 18:58:24 +00:00
child = child - > prev ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// we only end up here if the root node is empty
newNode - > parent = root ;
root - > key = key ;
root - > firstChild = newNode ;
root - > lastChild = newNode ;
root - > numChildren + + ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# ifdef BTREE_CHECK
CheckTree ( ) ;
# endif
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return newNode ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE void idBTree < objType , keyType , maxChildrenPerNode > : : Remove ( idBTreeNode < objType , keyType > * node )
{
idBTreeNode < objType , keyType > * parent ;
2012-11-26 18:58:24 +00:00
assert ( node - > object ! = NULL ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// unlink the node from it's parent
2012-11-28 15:47:07 +00:00
if ( node - > prev )
{
2012-11-26 18:58:24 +00:00
node - > prev - > next = node - > next ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
node - > parent - > firstChild = node - > next ;
}
2012-11-28 15:47:07 +00:00
if ( node - > next )
{
2012-11-26 18:58:24 +00:00
node - > next - > prev = node - > prev ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
node - > parent - > lastChild = node - > prev ;
}
node - > parent - > numChildren - - ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure there are no parent nodes with a single child
2012-11-28 15:47:07 +00:00
for ( parent = node - > parent ; parent ! = root & & parent - > numChildren < = 1 ; parent = parent - > parent )
{
if ( parent - > next )
{
2012-11-26 18:58:24 +00:00
parent = MergeNodes ( parent , parent - > next ) ;
2012-11-28 15:47:07 +00:00
}
else if ( parent - > prev )
{
2012-11-26 18:58:24 +00:00
parent = MergeNodes ( parent - > prev , parent ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// a parent may not use a key higher than the key of it's last child
2012-11-28 15:47:07 +00:00
if ( parent - > key > parent - > lastChild - > key )
{
2012-11-26 18:58:24 +00:00
parent - > key = parent - > lastChild - > key ;
}
2012-11-28 15:47:07 +00:00
if ( parent - > numChildren > maxChildrenPerNode )
{
2012-11-26 18:58:24 +00:00
SplitNode ( parent ) ;
break ;
}
}
2012-11-28 15:47:07 +00:00
for ( ; parent ! = NULL & & parent - > lastChild ! = NULL ; parent = parent - > parent )
{
2012-11-26 18:58:24 +00:00
// a parent may not use a key higher than the key of it's last child
2012-11-28 15:47:07 +00:00
if ( parent - > key > parent - > lastChild - > key )
{
2012-11-26 18:58:24 +00:00
parent - > key = parent - > lastChild - > key ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// free the node
FreeNode ( node ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// remove the root node if it has a single internal node as child
2012-11-28 15:47:07 +00:00
if ( root - > numChildren = = 1 & & root - > firstChild - > object = = NULL )
{
idBTreeNode < objType , keyType > * oldRoot = root ;
2012-11-26 18:58:24 +00:00
root - > firstChild - > parent = NULL ;
root = root - > firstChild ;
FreeNode ( oldRoot ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
# ifdef BTREE_CHECK
CheckTree ( ) ;
# endif
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE idBTreeNode < objType , keyType > * idBTree < objType , keyType , maxChildrenPerNode > : : NodeFind ( keyType key ) const
{
idBTreeNode < objType , keyType > * node ;
for ( node = root - > firstChild ; node ! = NULL ; node = node - > firstChild )
{
while ( node - > next )
{
if ( node - > key > = key )
{
2012-11-26 18:58:24 +00:00
break ;
}
node = node - > next ;
}
2012-11-28 15:47:07 +00:00
if ( node - > object )
{
if ( node - > key = = key )
{
2012-11-26 18:58:24 +00:00
return node ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
}
}
return NULL ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE idBTreeNode < objType , keyType > * idBTree < objType , keyType , maxChildrenPerNode > : : NodeFindSmallestLargerEqual ( keyType key ) const
{
idBTreeNode < objType , keyType > * node ;
if ( root = = NULL )
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
2012-11-28 15:47:07 +00:00
for ( node = root - > firstChild ; node ! = NULL ; node = node - > firstChild )
{
while ( node - > next )
{
if ( node - > key > = key )
{
2012-11-26 18:58:24 +00:00
break ;
}
node = node - > next ;
}
2012-11-28 15:47:07 +00:00
if ( node - > object )
{
if ( node - > key > = key )
{
2012-11-26 18:58:24 +00:00
return node ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
}
}
return NULL ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE idBTreeNode < objType , keyType > * idBTree < objType , keyType , maxChildrenPerNode > : : NodeFindLargestSmallerEqual ( keyType key ) const
{
idBTreeNode < objType , keyType > * node ;
if ( root = = NULL )
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
2012-11-28 15:47:07 +00:00
idBTreeNode < objType , keyType > * smaller = NULL ;
for ( node = root - > firstChild ; node ! = NULL ; node = node - > firstChild )
{
while ( node - > next )
{
if ( node - > key > = key )
{
2012-11-26 18:58:24 +00:00
break ;
}
smaller = node ;
node = node - > next ;
}
2012-11-28 15:47:07 +00:00
if ( node - > object )
{
if ( node - > key < = key )
{
2012-11-26 18:58:24 +00:00
return node ;
2012-11-28 15:47:07 +00:00
}
else if ( smaller = = NULL )
{
2012-11-26 18:58:24 +00:00
return NULL ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
node = smaller ;
2012-11-28 15:47:07 +00:00
if ( node - > object )
{
2012-11-26 18:58:24 +00:00
return node ;
}
}
}
}
return NULL ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE objType * idBTree < objType , keyType , maxChildrenPerNode > : : Find ( keyType key ) const
{
idBTreeNode < objType , keyType > * node = NodeFind ( key ) ;
if ( node = = NULL )
{
2012-11-26 18:58:24 +00:00
return NULL ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return node - > object ;
}
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE objType * idBTree < objType , keyType , maxChildrenPerNode > : : FindSmallestLargerEqual ( keyType key ) const
{
idBTreeNode < objType , keyType > * node = NodeFindSmallestLargerEqual ( key ) ;
if ( node = = NULL )
{
2012-11-26 18:58:24 +00:00
return NULL ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return node - > object ;
}
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE objType * idBTree < objType , keyType , maxChildrenPerNode > : : FindLargestSmallerEqual ( keyType key ) const
{
idBTreeNode < objType , keyType > * node = NodeFindLargestSmallerEqual ( key ) ;
if ( node = = NULL )
{
2012-11-26 18:58:24 +00:00
return NULL ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return node - > object ;
}
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE idBTreeNode < objType , keyType > * idBTree < objType , keyType , maxChildrenPerNode > : : GetRoot ( ) const
{
2012-11-26 18:58:24 +00:00
return root ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE int idBTree < objType , keyType , maxChildrenPerNode > : : GetNodeCount ( ) const
{
2012-11-26 18:58:24 +00:00
return nodeAllocator . GetAllocCount ( ) ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE idBTreeNode < objType , keyType > * idBTree < objType , keyType , maxChildrenPerNode > : : GetNext ( idBTreeNode < objType , keyType > * node ) const
{
if ( node - > firstChild )
{
2012-11-26 18:58:24 +00:00
return node - > firstChild ;
2012-11-28 15:47:07 +00:00
}
else
{
while ( node & & node - > next = = NULL )
{
2012-11-26 18:58:24 +00:00
node = node - > parent ;
}
return node ;
}
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE idBTreeNode < objType , keyType > * idBTree < objType , keyType , maxChildrenPerNode > : : GetNextLeaf ( idBTreeNode < objType , keyType > * node ) const
{
if ( node - > firstChild )
{
while ( node - > firstChild )
{
2012-11-26 18:58:24 +00:00
node = node - > firstChild ;
}
return node ;
2012-11-28 15:47:07 +00:00
}
else
{
while ( node & & node - > next = = NULL )
{
2012-11-26 18:58:24 +00:00
node = node - > parent ;
}
2012-11-28 15:47:07 +00:00
if ( node )
{
2012-11-26 18:58:24 +00:00
node = node - > next ;
2012-11-28 15:47:07 +00:00
while ( node - > firstChild )
{
2012-11-26 18:58:24 +00:00
node = node - > firstChild ;
}
return node ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return NULL ;
}
}
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE idBTreeNode < objType , keyType > * idBTree < objType , keyType , maxChildrenPerNode > : : AllocNode ( )
{
idBTreeNode < objType , keyType > * node = nodeAllocator . Alloc ( ) ;
2012-11-26 18:58:24 +00:00
node - > key = 0 ;
node - > parent = NULL ;
node - > next = NULL ;
node - > prev = NULL ;
node - > numChildren = 0 ;
node - > firstChild = NULL ;
node - > lastChild = NULL ;
node - > object = NULL ;
return node ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE void idBTree < objType , keyType , maxChildrenPerNode > : : FreeNode ( idBTreeNode < objType , keyType > * node )
{
2012-11-26 18:58:24 +00:00
nodeAllocator . Free ( node ) ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE void idBTree < objType , keyType , maxChildrenPerNode > : : SplitNode ( idBTreeNode < objType , keyType > * node )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
idBTreeNode < objType , keyType > * child , * newNode ;
2012-11-26 18:58:24 +00:00
// allocate a new node
newNode = AllocNode ( ) ;
newNode - > parent = node - > parent ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// divide the children over the two nodes
child = node - > firstChild ;
child - > parent = newNode ;
2012-11-28 15:47:07 +00:00
for ( i = 3 ; i < node - > numChildren ; i + = 2 )
{
2012-11-26 18:58:24 +00:00
child = child - > next ;
child - > parent = newNode ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
newNode - > key = child - > key ;
newNode - > numChildren = node - > numChildren / 2 ;
newNode - > firstChild = node - > firstChild ;
newNode - > lastChild = child ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
node - > numChildren - = newNode - > numChildren ;
node - > firstChild = child - > next ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
child - > next - > prev = NULL ;
child - > next = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add the new child to the parent before the split node
assert ( node - > parent - > numChildren < maxChildrenPerNode ) ;
2012-11-28 15:47:07 +00:00
if ( node - > prev )
{
2012-11-26 18:58:24 +00:00
node - > prev - > next = newNode ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
node - > parent - > firstChild = newNode ;
}
newNode - > prev = node - > prev ;
newNode - > next = node ;
node - > prev = newNode ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
node - > parent - > numChildren + + ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE idBTreeNode < objType , keyType > * idBTree < objType , keyType , maxChildrenPerNode > : : MergeNodes ( idBTreeNode < objType , keyType > * node1 , idBTreeNode < objType , keyType > * node2 )
{
idBTreeNode < objType , keyType > * child ;
2012-11-26 18:58:24 +00:00
assert ( node1 - > parent = = node2 - > parent ) ;
assert ( node1 - > next = = node2 & & node2 - > prev = = node1 ) ;
assert ( node1 - > object = = NULL & & node2 - > object = = NULL ) ;
assert ( node1 - > numChildren > = 1 & & node2 - > numChildren > = 1 ) ;
2012-11-28 15:47:07 +00:00
for ( child = node1 - > firstChild ; child - > next ; child = child - > next )
{
2012-11-26 18:58:24 +00:00
child - > parent = node2 ;
}
child - > parent = node2 ;
child - > next = node2 - > firstChild ;
node2 - > firstChild - > prev = child ;
node2 - > firstChild = node1 - > firstChild ;
node2 - > numChildren + = node1 - > numChildren ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// unlink the first node from the parent
2012-11-28 15:47:07 +00:00
if ( node1 - > prev )
{
2012-11-26 18:58:24 +00:00
node1 - > prev - > next = node2 ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
node1 - > parent - > firstChild = node2 ;
}
node2 - > prev = node1 - > prev ;
node2 - > parent - > numChildren - - ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
FreeNode ( node1 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return node2 ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE void idBTree < objType , keyType , maxChildrenPerNode > : : CheckTree_r ( idBTreeNode < objType , keyType > * node , int & numNodes ) const
{
2012-11-26 18:58:24 +00:00
int numChildren ;
2012-11-28 15:47:07 +00:00
idBTreeNode < objType , keyType > * child ;
2012-11-26 18:58:24 +00:00
numNodes + + ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// the root node may have zero children and leaf nodes always have zero children, all other nodes should have at least 2 and at most maxChildrenPerNode children
assert ( ( node = = root ) | | ( node - > object ! = NULL & & node - > numChildren = = 0 ) | | ( node - > numChildren > = 2 & & node - > numChildren < = maxChildrenPerNode ) ) ;
// the key of a node may never be larger than the key of it's last child
assert ( ( node - > lastChild = = NULL ) | | ( node - > key < = node - > lastChild - > key ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numChildren = 0 ;
2012-11-28 15:47:07 +00:00
for ( child = node - > firstChild ; child ; child = child - > next )
{
2012-11-26 18:58:24 +00:00
numChildren + + ;
// make sure the children are properly linked
2012-11-28 15:47:07 +00:00
if ( child - > prev = = NULL )
{
2012-11-26 18:58:24 +00:00
assert ( node - > firstChild = = child ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
assert ( child - > prev - > next = = child ) ;
}
2012-11-28 15:47:07 +00:00
if ( child - > next = = NULL )
{
2012-11-26 18:58:24 +00:00
assert ( node - > lastChild = = child ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
assert ( child - > next - > prev = = child ) ;
}
// recurse down the tree
CheckTree_r ( child , numNodes ) ;
}
// the number of children should equal the number of linked children
assert ( numChildren = = node - > numChildren ) ;
}
template < class objType , class keyType , int maxChildrenPerNode >
2012-11-28 15:47:07 +00:00
ID_INLINE void idBTree < objType , keyType , maxChildrenPerNode > : : CheckTree ( ) const
{
2012-11-26 18:58:24 +00:00
int numNodes = 0 ;
2012-11-28 15:47:07 +00:00
idBTreeNode < objType , keyType > * node , * lastNode ;
2012-11-26 18:58:24 +00:00
CheckTree_r ( root , numNodes ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// the number of nodes in the tree should equal the number of allocated nodes
assert ( numNodes = = nodeAllocator . GetAllocCount ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// all the leaf nodes should be ordered
lastNode = GetNextLeaf ( GetRoot ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( lastNode )
{
for ( node = GetNextLeaf ( lastNode ) ; node ; lastNode = node , node = GetNextLeaf ( node ) )
{
2012-11-26 18:58:24 +00:00
assert ( lastNode - > key < = node - > key ) ;
}
}
}
# endif /* !__BTREE_H__ */