gwnavruntime/kernel/SF_RadixTree.h Source File

SF_RadixTree.h
Go to the documentation of this file.
1 /*
2 * Copyright 2015 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 /**************************************************************************
8 
9 PublicHeader: Kernel
10 Filename : KY_RadixTree.h
11 Content : Template implementation for a simple radix tree.
12 Created : 2009
13 Authors : MaximShemanarev
14 
15 **************************************************************************/
16 
17 #ifndef INC_KY_Kernel_RadixTree_H
18 #define INC_KY_Kernel_RadixTree_H
19 
21 
22 namespace Kaim {
23 
24 // Intrusive radix tree adopted from Doug Lea malloc (public domain license).
25 // The tree works only with an integer key of UPInt type. The tree
26 // typically grows quickly to the number of bits in UPInt (32 or 64),
27 // but the tree height will never exceed this number. That is, it
28 // guarantees operation time of at most 32 or 64 operations respectively.
29 // In some sense it can be said that the access time is O(1), although
30 // the constant coefficient is rather hight.
31 //
32 // The tree requires the following accessor (as an example):
33 //
34 // struct TreeNodeAccessor
35 // {
36 // static UPInt GetKey (const TreeNode* n) { return n->Key; }
37 // static TreeNode* GetChild ( TreeNode* n, UPInt i) { return n->Child[i]; }
38 // static const TreeNode* GetChild (const TreeNode* n, UPInt i) { return n->Child[i]; }
39 // static TreeNode** GetChildPtr( TreeNode* n, UPInt i) { return &n->Child[i]; }
40 //
41 // static TreeNode* GetParent ( TreeNode* n) { return n->Parent; }
42 // static const TreeNode* GetParent (const TreeNode* n) { return n->Parent; }
43 //
44 // static void SetParent (TreeNode* n, TreeNode* p) { n->Parent = p; }
45 // static void SetChild (TreeNode* n, UPInt i, TreeNode* c) { n->Child[i] = c; }
46 // static void ClearLinks(TreeNode* n) { n->Parent = n->Child[0] = n->Child[1] = 0; }
47 //};
48 //
49 // Operations on the tree:
50 //
51 // T* Insert(T* node); // Returns NULL on success, or head node
52 // void Remove(T* node);
53 // const T* FindEqual(UPInt key) const;
54 // const T* FindGrEq (UPInt key) const;
55 // const T* FindLeEq (UPInt key) const;
56 //
57 //------------------------------------------------------------------------
58 template<class T, class Accessor> class RadixTree
59 {
60  enum { KeyBits = 8*sizeof(UPInt) };
61 
62 
63 public:
64  RadixTree() : Root(0) {}
65 
66  void Clear() { Root = 0; }
67 
68  // Insert node. Returns NULL on success, or the pointer to the
69  // node if the node with the same key already exists in the tree.
70  //--------------------------------------------------------------------
71  T* Insert(T* node)
72  {
73  T** root = &Root;
74 
75  Accessor::ClearLinks(node);
76 
77  if (Root == 0)
78  {
79  *root = node;
80  Accessor::SetParent(node, (T*)root);
81  }
82  else
83  {
84  UPInt key = Accessor::GetKey(node);
85  UPInt bits = key;
86  T* head = *root;
87  for (;;)
88  {
89  if (Accessor::GetKey(head) == key)
90  {
91  return head;
92  }
93  T** link = Accessor::GetChildPtr(head, (bits >> (KeyBits-1)) & 1);
94  bits <<= 1;
95 
96  if (*link != 0)
97  {
98  head = *link;
99  }
100  else
101  {
102  *link = node;
103  Accessor::SetParent(node, head);
104  break;
105  }
106  }
107  }
108  return 0;
109  }
110 
111 
112  //--------------------------------------------------------------------
113  void Remove(T* node, T* rotor)
114  {
115  T* parent = Accessor::GetParent(node);
116  if (parent != 0)
117  {
118  T** root = &Root;
119 
120  if (node == *root)
121  {
122  *root = rotor;
123  }
124  else
125  {
126  UPInt ic = Accessor::GetChild(parent, 0) != node;
127  Accessor::SetChild(parent, ic, rotor);
128  }
129 
130  if (rotor != 0)
131  {
132  T* child;
133 
134  Accessor::SetParent(rotor, parent);
135 
136  if ((child = Accessor::GetChild(node, 0)) != 0)
137  {
138  Accessor::SetChild(rotor, 0, child);
139  Accessor::SetParent(child, rotor);
140  }
141 
142  if ((child = Accessor::GetChild(node, 1)) != 0)
143  {
144  Accessor::SetChild(rotor, 1, child);
145  Accessor::SetParent(child, rotor);
146  }
147  }
148  }
149  Accessor::ClearLinks(node);
150  }
151 
152 
153  //--------------------------------------------------------------------
154  void Remove(T* node)
155  {
156  T* rotor;
157  T** rp;
158  if (((rotor = *(rp = Accessor::GetChildPtr(node, 1))) != 0) ||
159  ((rotor = *(rp = Accessor::GetChildPtr(node, 0))) != 0))
160  {
161  T** cp;
162  while ((*(cp = Accessor::GetChildPtr(rotor, 1)) != 0) ||
163  (*(cp = Accessor::GetChildPtr(rotor, 0)) != 0))
164  {
165  rotor = *(rp = cp);
166  }
167  *rp = 0;
168  }
169  Remove(node, rotor);
170  }
171 
172 
173  //--------------------------------------------------------------------
174  const T* FindEqual(UPInt key) const
175  {
176  const T* node = Root;
177  UPInt bits = key;
178  while (node && Accessor::GetKey(node) != key)
179  {
180  node = Accessor::GetChild(node, (bits >> (KeyBits-1)) & 1);
181  bits <<= 1;
182  }
183  return node;
184  }
185 
186  //--------------------------------------------------------------------
187  static const T* GetLeftmost(const T* node)
188  {
189  return Accessor::GetChild(node, Accessor::GetChild(node, 0) == 0);
190  }
191 
192  //--------------------------------------------------------------------
193  static const T* GetRightmost(const T* node)
194  {
195  return Accessor::GetChild(node, Accessor::GetChild(node, 1) != 0);
196  }
197 
198 
199  //--------------------------------------------------------------------
200  const T* FindGrEq(UPInt key) const
201  {
202  const T* best = 0;
203 
204  UPInt rkey = ~UPInt(0);
205  UPInt nkey;
206  UPInt diff;
207 
208  const T* node = Root;
209  if (node != 0)
210  {
211  // Traverse tree looking for node with node->Key == key
212  //--------------------------
213  const T* rst = 0; // The deepest untaken right subtree
214  UPInt bits = key;
215  for (;;)
216  {
217  const T* rt;
218 
219  nkey = Accessor::GetKey(node);
220  diff = nkey - key;
221  if (nkey >= key && diff < rkey)
222  {
223  best = node;
224  if ((rkey = diff) == 0)
225  {
226  return best;
227  }
228  }
229  rt = Accessor::GetChild(node, 1);
230  node = Accessor::GetChild(node, (bits >> (KeyBits-1)) & 1);
231  if (rt != 0 && rt != node)
232  {
233  rst = rt;
234  }
235  if (node == 0)
236  {
237  node = rst; // set node to least subtree holding Keys > key
238  break;
239  }
240  bits <<= 1;
241  }
242  }
243 
244  while (node)
245  {
246  // Find smallest of subtree.
247  //------------------------
248  nkey = Accessor::GetKey(node);
249  diff = nkey - key;
250  if (nkey >= key && diff < rkey)
251  {
252  rkey = diff;
253  best = node;
254  }
255  node = GetLeftmost(node);
256  }
257 
258  return best;
259  }
260 
261 
262  //--------------------------------------------------------------------
263  const T* FindLeEq(UPInt key) const
264  {
265  const T* best = 0;
266 
267  UPInt rkey = ~UPInt(0);
268  UPInt nkey;
269  UPInt diff;
270 
271  const T* node = Root;
272  if (node != 0)
273  {
274  // Traverse tree looking for node with node->Key == key
275  //--------------------------
276  const T* lst = 0; // The deepest untaken left subtree
277  UPInt bits = key;
278  for (;;)
279  {
280  const T* lt;
281  nkey = Accessor::GetKey(node);
282  diff = key - nkey;
283  if (nkey <= key && diff < rkey)
284  {
285  best = node;
286  if ((rkey = diff) == 0)
287  {
288  return best;
289  }
290  }
291  lt = Accessor::GetChild(node, 0);
292  node = Accessor::GetChild(node, (bits >> (KeyBits-1)) & 1);
293  if (lt != 0 && lt != node)
294  {
295  lst = lt;
296  }
297  if (node == 0)
298  {
299  node = lst; // set node to most subtree holding Keys < key
300  break;
301  }
302  bits <<= 1;
303  }
304  }
305 
306  while (node)
307  {
308  // Find biggest of subtree.
309  //------------------------
310  nkey = Accessor::GetKey(node);
311  diff = key - nkey;
312  if (nkey <= key && diff < rkey)
313  {
314  rkey = diff;
315  best = node;
316  }
317  node = GetRightmost(node);
318  }
319  return best;
320  }
321 
322  T* Root;
323 };
324 
325 
326 //------------------------------------------------------------------------
327 template<class T, class Accessor> class RadixTreeMulti
328 {
329 public:
330  //--------------------------------------------------------------------
331  void Insert(T* node)
332  {
333  node->pPrev = node;
334  node->pNext = node;
335  T* head = Tree.Insert(node);
336  if (head)
337  {
338  // Insert node next to the head one:
339  // Before: head <----------------> next1 <----> next2...
340  // After: head <----> node <----> next1 <----> next2...
341  //------------------------
342  node->pNext = head->pNext;
343  node->pPrev = head;
344  head->pNext = node;
345  node->pNext->pPrev = node;
346  }
347  }
348 
349  //--------------------------------------------------------------------
350  void Remove(T* node)
351  {
352  if (node->pPrev != node)
353  {
354  // The list isn't empty.
355  //------------------------
356  T* rotor;
357  T* f = node->pNext;
358  rotor = node->pPrev;
359 
360  f->pPrev = rotor;
361  rotor->pNext = f;
362  Tree.Remove(node, rotor);
363  }
364  else
365  {
366  Tree.Remove(node);
367  }
368  }
369 
370  //--------------------------------------------------------------------
371  const T* FindBestGrEq(UPInt key)
372  {
373  return Tree.FindGrEq(key);
374  }
375 
376  //--------------------------------------------------------------------
377  const T* FindBestLeEq(UPInt key)
378  {
379  return Tree.FindLeEq(key);
380  }
381 
382  //--------------------------------------------------------------------
383  T* PullBestGrEq(UPInt key)
384  {
385  T* node = (T*)Tree.FindGrEq(key);
386  if (node)
387  {
388  // Take the next node to reduce tree thrashing in Remove().
389  //------------------------
390  node = (T*)node->pNext;
391  Remove(node);
392  }
393  return node;
394  }
395 
396  //--------------------------------------------------------------------
397  T* PullBestLeEq(UPInt key)
398  {
399  T* node = (T*)Tree.FindLeEq(key);
400  if (node)
401  {
402  // Take the next node to reduce tree thrashing in Remove().
403  //------------------------
404  node = (T*)node->pNext;
405  Remove(node);
406  }
407  return node;
408  }
409 
410  RadixTree<T, Accessor> Tree;
411 };
412 
413 } // Scaleform
414 
415 #endif
Definition: gamekitcrowddispersion.h:20