The Pedigree Project  0.1
Tree.h
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #ifndef KERNEL_UTILITIES_TREE_H
21 #define KERNEL_UTILITIES_TREE_H
22 
23 #include "pedigree/kernel/compiler.h"
24 #include "pedigree/kernel/processor/types.h"
25 #include "pedigree/kernel/utilities/Iterator.h"
26 
32 template <class K, class E>
34 {
35  private:
37  struct Node
38  {
39  K key;
40  E element;
41  struct Node *leftChild = nullptr;
42  struct Node *rightChild = nullptr;
43  struct Node *parent = nullptr;
44  size_t height = 0;
45  };
46 
47  public:
52  {
53  public:
54  IteratorNode() : value(0), pNode(0), pPreviousNode(0)
55  {
56  }
57  IteratorNode(Node *node, Node *prev, size_t n)
58  : value(node), pNode(node), pPreviousNode(prev)
59  {
60  // skip the root node, get to the lowest node in the tree
61  if (n > 1)
62  traverseNext();
63  value = pNode;
64  }
65 
66  IteratorNode *next()
67  {
68  traverseNext();
69 
70  value = pNode;
71 
72  return this;
73  }
74  IteratorNode *previous()
75  {
76  return 0;
77  }
78 
79  void reset(Node *node, Node *prev, size_t n)
80  {
81  value = pNode = node;
82  pPreviousNode = prev;
83  if (n > 1)
84  traverseNext();
85  value = pNode;
86  }
87 
88  Node *value;
89 
90  private:
91  Node *pNode;
92  Node *pPreviousNode;
93 
94  void traverseNext()
95  {
96  if (pNode == 0)
97  return;
98 
99  if ((pPreviousNode == pNode->parent) && pNode->leftChild)
100  {
101  pPreviousNode = pNode;
102  pNode = pNode->leftChild;
103  traverseNext();
104  }
105  else if (
106  (((pNode->leftChild) && (pPreviousNode == pNode->leftChild)) ||
107  ((!pNode->leftChild) && (pPreviousNode != pNode))) &&
108  (pPreviousNode != pNode->rightChild))
109  {
110  pPreviousNode = pNode;
111  }
112  else if ((pPreviousNode == pNode) && pNode->rightChild)
113  {
114  pPreviousNode = pNode;
115  pNode = pNode->rightChild;
116  traverseNext();
117  }
118  else
119  {
120  pPreviousNode = pNode;
121  pNode = pNode->parent;
122  traverseNext();
123  }
124  }
125  };
126 
127  // typedef void** Iterator;
128 
129  typedef ::TreeIterator<
130  E, IteratorNode, &IteratorNode::previous, &IteratorNode::next, K>
131  Iterator;
133  typedef E const *ConstIterator;
134 
136  Tree() : root(0), nItems(0), m_Begin(0)
137  {
138  }
139 
142  Tree(const Tree &x) : root(0), nItems(0), m_Begin(0)
143  {
144  copyFrom(x);
145  }
146 
149  {
150  clear();
151  delete m_Begin;
152  }
153 
156  Tree &operator=(const Tree &x)
157  {
158  copyFrom(x);
159 
160  return *this;
161  }
162 
165  size_t count() const
166  {
167  return nItems;
168  }
169 
173  void insert(const K &key, const E &value)
174  {
175  Node *insertionNode = createInsertionNode(key);
176  insertionNode->element = value;
177  ++nItems;
178  }
179 
183  void insert(const K &key, E &&value)
184  {
185  Node *insertionNode = createInsertionNode(key);
186  insertionNode->element = pedigree_std::move(value);
187  ++nItems;
188  }
189 
192  E lookup(const K &key) const
193  {
194  Node *n = root;
195  while (n != 0)
196  {
197  if (n->key == key)
198  return n->element;
199  else if (n->key > key)
200  n = n->leftChild;
201  else
202  n = n->rightChild;
203  }
204  return 0;
205  }
206 
209  const E &lookupRef(const K &key, const E &failed=E()) const
210  {
211  Node *n = root;
212  while (n != 0)
213  {
214  if (n->key == key)
215  return n->element;
216  else if (n->key > key)
217  n = n->leftChild;
218  else
219  n = n->rightChild;
220  }
221  return failed;
222  }
223 
226  bool contains(const K &key) const
227  {
228  Node *n = root;
229  while (n != 0)
230  {
231  if (n->key == key)
232  return true;
233  else if (n->key > key)
234  n = n->leftChild;
235  else
236  n = n->rightChild;
237  }
238  return false;
239  }
240 
242  void remove(const K &key)
243  {
244  Node *n = root;
245  while (n != 0)
246  {
247  if (n->key == key)
248  break;
249  else if (n->key > key)
250  n = n->leftChild;
251  else
252  n = n->rightChild;
253  }
254 
255  Node *orign = n;
256  if (n == 0)
257  return;
258 
259  while (n->leftChild || n->rightChild) // While n is not a leaf.
260  {
261  size_t hl = height(n->leftChild);
262  size_t hr = height(n->rightChild);
263  if (hl == 0)
264  rotateLeft(n); // N is now a leaf.
265  else if (hr == 0)
266  rotateRight(n); // N is now a leaf.
267  else if (hl <= hr)
268  {
269  rotateRight(n);
270  rotateLeft(n); // These are NOT inverse operations -
271  // rotateRight changes n's position.
272  }
273  else
274  {
275  rotateLeft(n);
276  rotateRight(n);
277  }
278  }
279 
280  // N is now a leaf, so can be easily pruned.
281  if (n->parent == 0)
282  root = 0;
283  else
284  {
285  if (n->parent->leftChild == n)
286  n->parent->leftChild = 0;
287  else
288  n->parent->rightChild = 0;
289  }
290 
291  // Work our way up the path, balancing.
292  while (n)
293  {
294  int b = balanceFactor(n);
295  if ((b < -1) || (b > 1))
296  rebalanceNode(n);
297  n = n->parent;
298  }
299 
300  delete orign;
301  nItems--;
302  }
303 
305  void clear()
306  {
307  traverseNode_Remove(root);
308  root = 0;
309  nItems = 0;
310 
311  delete m_Begin;
312  m_Begin = 0;
313  }
314 
316  void erase(Iterator iter)
317  {
318  // Remove the key from the tree.
319  remove(iter.key());
320 
321  // Passed iterator is now invalid.
322  }
323 
326  Iterator begin()
327  {
328  // If there is no node already, create a new one
329  if (!m_Begin)
330  m_Begin = new IteratorNode(root, 0, nItems);
331 
332  // Reset the iterator node
333  else
334  m_Begin->reset(root, 0, nItems);
335  // m_Begin = new (static_cast<void*>(m_Begin)) IteratorNode(root, 0,
336  // nItems);
337 
338  return Iterator(m_Begin);
339  }
342  ConstIterator begin() const
343  {
344  return 0;
345  }
348  Iterator end()
349  {
350  return Iterator(0);
351  }
354  ConstIterator end() const
355  {
356  return 0;
357  }
358 
359  private:
360  void copyFrom(const Tree &other)
361  {
362  clear();
363  // Traverse the tree, adding everything encountered.
364  traverseNode_Insert(other.root);
365 
366  if (m_Begin)
367  delete m_Begin;
368  m_Begin = new IteratorNode(root, 0, nItems);
369  }
370 
371  void rotateLeft(Node *n)
372  {
373  // See Cormen,Lieserson,Rivest&Stein pp-> 278 for pseudocode.
374  Node *y = n->rightChild; // Set Y.
375 
376  n->rightChild =
377  y->leftChild; // Turn Y's left subtree into N's right subtree.
378  if (y->leftChild != 0)
379  y->leftChild->parent = n;
380 
381  y->parent = n->parent; // Link Y's parent to N's parent.
382  if (n->parent == 0)
383  root = y;
384  else if (n == n->parent->leftChild)
385  n->parent->leftChild = y;
386  else
387  n->parent->rightChild = y;
388  y->leftChild = n;
389  n->parent = y;
390  }
391 
392  void rotateRight(Node *n)
393  {
394  Node *y = n->leftChild;
395 
396  n->leftChild = y->rightChild;
397  if (y->rightChild != 0)
398  y->rightChild->parent = n;
399 
400  y->parent = n->parent;
401  if (n->parent == 0)
402  root = y;
403  else if (n == n->parent->leftChild)
404  n->parent->leftChild = y;
405  else
406  n->parent->rightChild = y;
407 
408  y->rightChild = n;
409  n->parent = y;
410  }
411 
412  size_t height(Node *n)
413  {
414  // Assumes: n's children's heights are up to date. Will always be true
415  // if balanceFactor
416  // is called in a bottom-up fashion.
417  if (n == 0)
418  return 0;
419 
420  size_t tempL = 0;
421  size_t tempR = 0;
422 
423  if (n->leftChild != 0)
424  tempL = n->leftChild->height;
425  if (n->rightChild != 0)
426  tempR = n->rightChild->height;
427 
428  tempL++; // Account for the height increase stepping up to us, its
429  // parent.
430  tempR++;
431 
432  if (tempL > tempR) // If one is actually bigger than the other, return
433  // that, else return the other.
434  {
435  n->height = tempL;
436  return tempL;
437  }
438  else
439  {
440  n->height = tempR;
441  return tempR;
442  }
443  }
444 
445  int balanceFactor(Node *n)
446  {
447  return static_cast<int>(height(n->rightChild)) -
448  static_cast<int>(height(n->leftChild));
449  }
450 
451  void rebalanceNode(Node *n)
452  {
453  // This way of choosing which rotation to do took me AGES to find...
454  // See
455  // http://www.cmcrossroads.com/bradapp/ftp/src/libs/C++/AvlTrees.html
456  int balance = balanceFactor(n);
457  if (balance < -1) // If it's left imbalanced, we need a right rotation.
458  {
459  if (balanceFactor(n->leftChild) >
460  0) // If its left child is right heavy...
461  {
462  // We need a RL rotation - left rotate n's left child, then
463  // right rotate N.
464  rotateLeft(n->leftChild);
465  rotateRight(n);
466  }
467  else
468  {
469  // RR rotation will do.
470  rotateRight(n);
471  }
472  }
473  else if (balance > 1)
474  {
475  if (balanceFactor(n->rightChild) <
476  0) // If its right child is left heavy...
477  {
478  // We need a LR rotation; Right rotate N's right child, then
479  // left rotate N.
480  rotateRight(n->rightChild);
481  rotateLeft(n);
482  }
483  else
484  {
485  // LL rotation.
486  rotateLeft(n);
487  }
488  }
489  }
490 
491  void traverseNode_Insert(Node *n)
492  {
493  if (!n)
494  return;
495  insert(n->key, n->element);
496  traverseNode_Insert(n->leftChild);
497  traverseNode_Insert(n->rightChild);
498  }
499 
500  void traverseNode_Remove(Node *n)
501  {
502  if (!n)
503  return;
504 
505  Node *left = n->leftChild;
506  Node *right = n->rightChild;
507  n->leftChild = nullptr;
508  n->rightChild = nullptr;
509 
510  traverseNode_Remove(left);
511  traverseNode_Remove(right);
512  delete n;
513  }
514 
515  Node *createInsertionNode(const K &key)
516  {
517  Node *insertionNode = nullptr;
518 
519  if (root == 0)
520  {
521  insertionNode = new Node;
522  insertionNode->key = key;
523 
524  root = insertionNode; // We are the root node.
525 
526  if (m_Begin)
527  {
528  delete m_Begin;
529  }
530  m_Begin = new IteratorNode(root, 0, nItems);
531  }
532  else
533  {
534  // Traverse the tree.
535  Node *currentNode = root;
536 
537  bool inserted = false;
538  while (!inserted)
539  {
540  if (key > currentNode->key)
541  {
542  if (currentNode->rightChild ==
543  0) // We have found our insert point.
544  {
545  insertionNode = new Node;
546  insertionNode->key = key;
547  insertionNode->parent = currentNode;
548  currentNode->rightChild = insertionNode;
549  inserted = true;
550  }
551  else
552  {
553  currentNode = currentNode->rightChild;
554  }
555  }
556  else if (key == currentNode->key)
557  {
558  // overwrite existing value
559  insertionNode = currentNode;
560  inserted = true;
561  }
562  else
563  {
564  if (currentNode->leftChild ==
565  0) // We have found our insert point.
566  {
567  insertionNode = new Node;
568  insertionNode->key = key;
569  insertionNode->parent = currentNode;
570  currentNode->leftChild = insertionNode;
571  inserted = true;
572  }
573  else
574  {
575  currentNode = currentNode->leftChild;
576  }
577  }
578  }
579 
580  // The value has been inserted, but has that messed up the balance
581  // of the tree?
582  while (currentNode)
583  {
584  int b = balanceFactor(currentNode);
585  if ((b < -1) || (b > 1))
586  {
587  rebalanceNode(currentNode);
588  }
589  currentNode = currentNode->parent;
590  }
591  }
592 
593  return insertionNode;
594  }
595 
596  Node *root;
597  size_t nItems;
598 
599  IteratorNode *m_Begin;
600 };
601 
602 // External specializations.
603 extern template class Tree<void *, void *>; // IWYU pragma: keep
604 extern template class Tree<int8_t, void *>; // IWYU pragma: keep
605 extern template class Tree<int16_t, void *>; // IWYU pragma: keep
606 extern template class Tree<int32_t, void *>; // IWYU pragma: keep
607 extern template class Tree<int64_t, void *>; // IWYU pragma: keep
608 extern template class Tree<uint8_t, void *>; // IWYU pragma: keep
609 extern template class Tree<uint16_t, void *>; // IWYU pragma: keep
610 extern template class Tree<uint32_t, void *>; // IWYU pragma: keep
611 extern template class Tree<uint64_t, void *>; // IWYU pragma: keep
612 extern template class Tree<int8_t, int8_t>; // IWYU pragma: keep
613 extern template class Tree<int16_t, int16_t>; // IWYU pragma: keep
614 extern template class Tree<int32_t, int32_t>; // IWYU pragma: keep
615 extern template class Tree<int64_t, int64_t>; // IWYU pragma: keep
616 extern template class Tree<uint8_t, uint8_t>; // IWYU pragma: keep
617 extern template class Tree<uint16_t, uint16_t>; // IWYU pragma: keep
618 extern template class Tree<uint32_t, uint32_t>; // IWYU pragma: keep
619 extern template class Tree<uint64_t, uint64_t>; // IWYU pragma: keep
620 
623 #endif
Iterator end()
Definition: Tree.h:348
const E & lookupRef(const K &key, const E &failed=E()) const
Definition: Tree.h:209
void clear()
Definition: Tree.h:305
~Tree()
Definition: Tree.h:148
Tree(const Tree &x)
Definition: Tree.h:142
void insert(const K &key, E &&value)
Definition: Tree.h:183
ConstIterator begin() const
Definition: Tree.h:342
size_t count() const
Definition: Tree.h:165
Tree & operator=(const Tree &x)
Definition: Tree.h:156
Tree()
Definition: Tree.h:136
void insert(const K &key, const E &value)
Definition: Tree.h:173
Iterator begin()
Definition: Tree.h:326
A key/value dictionary.
Definition: Tree.h:33
bool contains(const K &key) const
Definition: Tree.h:226
E const * ConstIterator
Definition: Tree.h:133
An iterator applicable for many data structures.
Definition: Iterator.h:180
void erase(Iterator iter)
Definition: Tree.h:316
ConstIterator end() const
Definition: Tree.h:354
E lookup(const K &key) const
Definition: Tree.h:192