doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
BTree.h
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 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 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 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.
25 
26 ===========================================================================
27 */
28 
29 #ifndef __BTREE_H__
30 #define __BTREE_H__
31 
32 /*
33 ===============================================================================
34 
35  Balanced Search Tree
36 
37 ===============================================================================
38 */
39 
40 //#define BTREE_CHECK
41 
42 template< class objType, class keyType >
43 class idBTreeNode {
44 public:
45  keyType key; // key used for sorting
46  objType * object; // if != NULL pointer to object stored in leaf node
47  idBTreeNode * parent; // parent node
48  idBTreeNode * next; // next sibling
49  idBTreeNode * prev; // prev sibling
50  int numChildren; // number of children
51  idBTreeNode * firstChild; // first child
52  idBTreeNode * lastChild; // last child
53 };
54 
55 
56 template< class objType, class keyType, int maxChildrenPerNode >
57 class idBTree {
58 public:
59  idBTree( void );
60  ~idBTree( void );
61 
62  void Init( void );
63  void Shutdown( void );
64 
65  idBTreeNode<objType,keyType> * Add( objType *object, keyType key ); // add an object to the tree
66  void Remove( idBTreeNode<objType,keyType> *node ); // remove an object node from the tree
67 
68  objType * Find( keyType key ) const; // find an object using the given key
69  objType * FindSmallestLargerEqual( keyType key ) const; // find an object with the smallest key larger equal the given key
70  objType * FindLargestSmallerEqual( keyType key ) const; // find an object with the largest key smaller equal the given key
71 
72  idBTreeNode<objType,keyType> * GetRoot( void ) const; // returns the root node of the tree
73  int GetNodeCount( void ) const; // returns the total number of nodes in the tree
74  idBTreeNode<objType,keyType> * GetNext( idBTreeNode<objType,keyType> *node ) const; // goes through all nodes of the tree
75  idBTreeNode<objType,keyType> * GetNextLeaf( idBTreeNode<objType,keyType> *node ) const; // goes through all leaf nodes of the tree
76 
77 private:
80 
85 
86  void CheckTree_r( idBTreeNode<objType,keyType> *node, int &numNodes ) const;
87  void CheckTree( void ) const;
88 };
89 
90 
91 template< class objType, class keyType, int maxChildrenPerNode >
93  assert( maxChildrenPerNode >= 4 );
94  root = NULL;
95 }
96 
97 template< class objType, class keyType, int maxChildrenPerNode >
99  Shutdown();
100 }
101 
102 template< class objType, class keyType, int maxChildrenPerNode >
104  root = AllocNode();
105 }
106 
107 template< class objType, class keyType, int maxChildrenPerNode >
109  nodeAllocator.Shutdown();
110  root = NULL;
111 }
112 
113 template< class objType, class keyType, int maxChildrenPerNode >
115  idBTreeNode<objType,keyType> *node, *child, *newNode;
116 
117  if ( root->numChildren >= maxChildrenPerNode ) {
118  newNode = AllocNode();
119  newNode->key = root->key;
120  newNode->firstChild = root;
121  newNode->lastChild = root;
122  newNode->numChildren = 1;
123  root->parent = newNode;
124  SplitNode( root );
125  root = newNode;
126  }
127 
128  newNode = AllocNode();
129  newNode->key = key;
130  newNode->object = object;
131 
132  for ( node = root; node->firstChild != NULL; node = child ) {
133 
134  if ( key > node->key ) {
135  node->key = key;
136  }
137 
138  // find the first child with a key larger equal to the key of the new node
139  for( child = node->firstChild; child->next; child = child->next ) {
140  if ( key <= child->key ) {
141  break;
142  }
143  }
144 
145  if ( child->object ) {
146 
147  if ( key <= child->key ) {
148  // insert new node before child
149  if ( child->prev ) {
150  child->prev->next = newNode;
151  } else {
152  node->firstChild = newNode;
153  }
154  newNode->prev = child->prev;
155  newNode->next = child;
156  child->prev = newNode;
157  } else {
158  // insert new node after child
159  if ( child->next ) {
160  child->next->prev = newNode;
161  } else {
162  node->lastChild = newNode;
163  }
164  newNode->prev = child;
165  newNode->next = child->next;
166  child->next = newNode;
167  }
168 
169  newNode->parent = node;
170  node->numChildren++;
171 
172 #ifdef BTREE_CHECK
173  CheckTree();
174 #endif
175 
176  return newNode;
177  }
178 
179  // make sure the child has room to store another node
180  if ( child->numChildren >= maxChildrenPerNode ) {
181  SplitNode( child );
182  if ( key <= child->prev->key ) {
183  child = child->prev;
184  }
185  }
186  }
187 
188  // we only end up here if the root node is empty
189  newNode->parent = root;
190  root->key = key;
191  root->firstChild = newNode;
192  root->lastChild = newNode;
193  root->numChildren++;
194 
195 #ifdef BTREE_CHECK
196  CheckTree();
197 #endif
198 
199  return newNode;
200 }
201 
202 template< class objType, class keyType, int maxChildrenPerNode >
205 
206  assert( node->object != NULL );
207 
208  // unlink the node from it's parent
209  if ( node->prev ) {
210  node->prev->next = node->next;
211  } else {
212  node->parent->firstChild = node->next;
213  }
214  if ( node->next ) {
215  node->next->prev = node->prev;
216  } else {
217  node->parent->lastChild = node->prev;
218  }
219  node->parent->numChildren--;
220 
221  // make sure there are no parent nodes with a single child
222  for ( parent = node->parent; parent != root && parent->numChildren <= 1; parent = parent->parent ) {
223 
224  if ( parent->next ) {
225  parent = MergeNodes( parent, parent->next );
226  } else if ( parent->prev ) {
227  parent = MergeNodes( parent->prev, parent );
228  }
229 
230  // a parent may not use a key higher than the key of it's last child
231  if ( parent->key > parent->lastChild->key ) {
232  parent->key = parent->lastChild->key;
233  }
234 
235  if ( parent->numChildren > maxChildrenPerNode ) {
236  SplitNode( parent );
237  break;
238  }
239  }
240  for ( ; parent != NULL && parent->lastChild != NULL; parent = parent->parent ) {
241  // a parent may not use a key higher than the key of it's last child
242  if ( parent->key > parent->lastChild->key ) {
243  parent->key = parent->lastChild->key;
244  }
245  }
246 
247  // free the node
248  FreeNode( node );
249 
250  // remove the root node if it has a single internal node as child
251  if ( root->numChildren == 1 && root->firstChild->object == NULL ) {
252  idBTreeNode<objType,keyType> *oldRoot = root;
253  root->firstChild->parent = NULL;
254  root = root->firstChild;
255  FreeNode( oldRoot );
256  }
257 
258 #ifdef BTREE_CHECK
259  CheckTree();
260 #endif
261 }
262 
263 template< class objType, class keyType, int maxChildrenPerNode >
264 ID_INLINE objType *idBTree<objType,keyType,maxChildrenPerNode>::Find( keyType key ) const {
266 
267  for ( node = root->firstChild; node != NULL; node = node->firstChild ) {
268  while( node->next ) {
269  if ( node->key >= key ) {
270  break;
271  }
272  node = node->next;
273  }
274  if ( node->object ) {
275  if ( node->key == key ) {
276  return node->object;
277  } else {
278  return NULL;
279  }
280  }
281  }
282  return NULL;
283 }
284 
285 template< class objType, class keyType, int maxChildrenPerNode >
288 
289  for ( node = root->firstChild; node != NULL; node = node->firstChild ) {
290  while( node->next ) {
291  if ( node->key >= key ) {
292  break;
293  }
294  node = node->next;
295  }
296  if ( node->object ) {
297  if ( node->key >= key ) {
298  return node->object;
299  } else {
300  return NULL;
301  }
302  }
303  }
304  return NULL;
305 }
306 
307 template< class objType, class keyType, int maxChildrenPerNode >
310 
311  for ( node = root->lastChild; node != NULL; node = node->lastChild ) {
312  while( node->prev ) {
313  if ( node->key <= key ) {
314  break;
315  }
316  node = node->prev;
317  }
318  if ( node->object ) {
319  if ( node->key <= key ) {
320  return node->object;
321  } else {
322  return NULL;
323  }
324  }
325  }
326  return NULL;
327 }
328 
329 template< class objType, class keyType, int maxChildrenPerNode >
331  return root;
332 }
333 
334 template< class objType, class keyType, int maxChildrenPerNode >
336  return nodeAllocator.GetAllocCount();
337 }
338 
339 template< class objType, class keyType, int maxChildrenPerNode >
341  if ( node->firstChild ) {
342  return node->firstChild;
343  } else {
344  while( node && node->next == NULL ) {
345  node = node->parent;
346  }
347  return node;
348  }
349 }
350 
351 template< class objType, class keyType, int maxChildrenPerNode >
353  if ( node->firstChild ) {
354  while ( node->firstChild ) {
355  node = node->firstChild;
356  }
357  return node;
358  } else {
359  while( node && node->next == NULL ) {
360  node = node->parent;
361  }
362  if ( node ) {
363  node = node->next;
364  while ( node->firstChild ) {
365  node = node->firstChild;
366  }
367  return node;
368  } else {
369  return NULL;
370  }
371  }
372 }
373 
374 template< class objType, class keyType, int maxChildrenPerNode >
376  idBTreeNode<objType,keyType> *node = nodeAllocator.Alloc();
377  node->key = 0;
378  node->parent = NULL;
379  node->next = NULL;
380  node->prev = NULL;
381  node->numChildren = 0;
382  node->firstChild = NULL;
383  node->lastChild = NULL;
384  node->object = NULL;
385  return node;
386 }
387 
388 template< class objType, class keyType, int maxChildrenPerNode >
390  nodeAllocator.Free( node );
391 }
392 
393 template< class objType, class keyType, int maxChildrenPerNode >
395  int i;
396  idBTreeNode<objType,keyType> *child, *newNode;
397 
398  // allocate a new node
399  newNode = AllocNode();
400  newNode->parent = node->parent;
401 
402  // divide the children over the two nodes
403  child = node->firstChild;
404  child->parent = newNode;
405  for ( i = 3; i < node->numChildren; i += 2 ) {
406  child = child->next;
407  child->parent = newNode;
408  }
409 
410  newNode->key = child->key;
411  newNode->numChildren = node->numChildren / 2;
412  newNode->firstChild = node->firstChild;
413  newNode->lastChild = child;
414 
415  node->numChildren -= newNode->numChildren;
416  node->firstChild = child->next;
417 
418  child->next->prev = NULL;
419  child->next = NULL;
420 
421  // add the new child to the parent before the split node
422  assert( node->parent->numChildren < maxChildrenPerNode );
423 
424  if ( node->prev ) {
425  node->prev->next = newNode;
426  } else {
427  node->parent->firstChild = newNode;
428  }
429  newNode->prev = node->prev;
430  newNode->next = node;
431  node->prev = newNode;
432 
433  node->parent->numChildren++;
434 }
435 
436 template< class objType, class keyType, int maxChildrenPerNode >
439 
440  assert( node1->parent == node2->parent );
441  assert( node1->next == node2 && node2->prev == node1 );
442  assert( node1->object == NULL && node2->object == NULL );
443  assert( node1->numChildren >= 1 && node2->numChildren >= 1 );
444 
445  for ( child = node1->firstChild; child->next; child = child->next ) {
446  child->parent = node2;
447  }
448  child->parent = node2;
449  child->next = node2->firstChild;
450  node2->firstChild->prev = child;
451  node2->firstChild = node1->firstChild;
452  node2->numChildren += node1->numChildren;
453 
454  // unlink the first node from the parent
455  if ( node1->prev ) {
456  node1->prev->next = node2;
457  } else {
458  node1->parent->firstChild = node2;
459  }
460  node2->prev = node1->prev;
461  node2->parent->numChildren--;
462 
463  FreeNode( node1 );
464 
465  return node2;
466 }
467 
468 template< class objType, class keyType, int maxChildrenPerNode >
470  int numChildren;
472 
473  numNodes++;
474 
475  // 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
476  assert( ( node == root ) || ( node->object != NULL && node->numChildren == 0 ) || ( node->numChildren >= 2 && node->numChildren <= maxChildrenPerNode ) );
477  // the key of a node may never be larger than the key of it's last child
478  assert( ( node->lastChild == NULL ) || ( node->key <= node->lastChild->key ) );
479 
480  numChildren = 0;
481  for ( child = node->firstChild; child; child = child->next ) {
482  numChildren++;
483  // make sure the children are properly linked
484  if ( child->prev == NULL ) {
485  assert( node->firstChild == child );
486  } else {
487  assert( child->prev->next == child );
488  }
489  if ( child->next == NULL ) {
490  assert( node->lastChild == child );
491  } else {
492  assert( child->next->prev == child );
493  }
494  // recurse down the tree
495  CheckTree_r( child, numNodes );
496  }
497  // the number of children should equal the number of linked children
498  assert( numChildren == node->numChildren );
499 }
500 
501 template< class objType, class keyType, int maxChildrenPerNode >
503  int numNodes = 0;
504  idBTreeNode<objType,keyType> *node, *lastNode;
505 
506  CheckTree_r( root, numNodes );
507 
508  // the number of nodes in the tree should equal the number of allocated nodes
509  assert( numNodes == nodeAllocator.GetAllocCount() );
510 
511  // all the leaf nodes should be ordered
512  lastNode = GetNextLeaf( GetRoot() );
513  if ( lastNode ) {
514  for ( node = GetNextLeaf( lastNode ); node; lastNode = node, node = GetNextLeaf( node ) ) {
515  assert( lastNode->key <= node->key );
516  }
517  }
518 }
519 
520 #endif /* !__BTREE_H__ */
assert(prefInfo.fullscreenBtn)
idBTreeNode * prev
Definition: BTree.h:49
void FreeNode(idBTreeNode< objType, keyType > *node)
Definition: BTree.h:389
int numChildren
Definition: BTree.h:50
idBTreeNode< objType, keyType > * root
Definition: BTree.h:78
idBTreeNode * next
Definition: BTree.h:48
int i
Definition: process.py:33
idBTree(void)
Definition: BTree.h:92
~idBTree(void)
Definition: BTree.h:98
void CheckTree_r(idBTreeNode< objType, keyType > *node, int &numNodes) const
Definition: BTree.h:469
keyType key
Definition: BTree.h:45
void Init(void)
Definition: BTree.h:103
idBlockAlloc< idBTreeNode< objType, keyType >, 128 > nodeAllocator
Definition: BTree.h:79
idBTreeNode< objType, keyType > * MergeNodes(idBTreeNode< objType, keyType > *node1, idBTreeNode< objType, keyType > *node2)
Definition: BTree.h:437
#define NULL
Definition: Lib.h:88
void Remove(idBTreeNode< objType, keyType > *node)
Definition: BTree.h:203
idBTreeNode< objType, keyType > * GetNextLeaf(idBTreeNode< objType, keyType > *node) const
Definition: BTree.h:352
idBTreeNode< objType, keyType > * Add(objType *object, keyType key)
Definition: BTree.h:114
objType * object
Definition: BTree.h:46
idBTreeNode< objType, keyType > * AllocNode(void)
Definition: BTree.h:375
void SplitNode(idBTreeNode< objType, keyType > *node)
Definition: BTree.h:394
idBTreeNode * firstChild
Definition: BTree.h:51
node_t * AllocNode(void)
Definition: ubrush.cpp:487
Definition: BTree.h:57
void Shutdown(void)
Definition: BTree.h:108
idBTreeNode< objType, keyType > * GetNext(idBTreeNode< objType, keyType > *node) const
Definition: BTree.h:340
idBTreeNode< objType, keyType > * GetRoot(void) const
Definition: BTree.h:330
objType * Find(keyType key) const
Definition: BTree.h:264
int GetNodeCount(void) const
Definition: BTree.h:335
idBTreeNode * parent
Definition: BTree.h:47
objType * FindSmallestLargerEqual(keyType key) const
Definition: BTree.h:286
objType * FindLargestSmallerEqual(keyType key) const
Definition: BTree.h:308
void CheckTree(void) const
Definition: BTree.h:502
idBTreeNode * lastChild
Definition: BTree.h:52