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
32template <class K, class E>
33class EXPORTED_PUBLIC Tree {
34 private:
36 struct Node {
37 K key;
38 E element;
39 struct Node* leftChild = nullptr;
40 struct Node* rightChild = nullptr;
41 struct Node* parent = nullptr;
42 size_t height = 0;
43 };
44
45 public:
50 public:
51 IteratorNode() : value(0), pNode(0), pPreviousNode(0) {}
52 IteratorNode(Node* node, Node* prev, size_t n) : value(node), pNode(node), pPreviousNode(prev) {
53 // skip the root node, get to the lowest node in the tree
54 if (n > 1)
55 traverseNext();
56 value = pNode;
57 }
58
59 IteratorNode* next() {
60 traverseNext();
61
62 value = pNode;
63
64 return this;
65 }
66 IteratorNode* previous() {
67 return 0;
68 }
69
70 void reset(Node* node, Node* prev, size_t n) {
71 value = pNode = node;
72 pPreviousNode = prev;
73 if (n > 1)
74 traverseNext();
75 value = pNode;
76 }
77
78 Node* value;
79
80 private:
81 Node* pNode;
82 Node* pPreviousNode;
83
84 void traverseNext() {
85 if (pNode == 0)
86 return;
87
88 if ((pPreviousNode == pNode->parent) && pNode->leftChild) {
89 pPreviousNode = pNode;
90 pNode = pNode->leftChild;
91 traverseNext();
92 } else if ((((pNode->leftChild) && (pPreviousNode == pNode->leftChild)) ||
93 ((!pNode->leftChild) && (pPreviousNode != pNode))) &&
94 (pPreviousNode != pNode->rightChild)) {
95 pPreviousNode = pNode;
96 } else if ((pPreviousNode == pNode) && pNode->rightChild) {
97 pPreviousNode = pNode;
98 pNode = pNode->rightChild;
99 traverseNext();
100 } else {
101 pPreviousNode = pNode;
102 pNode = pNode->parent;
103 traverseNext();
104 }
105 }
106 };
107
108 // typedef void** Iterator;
109
110 typedef ::TreeIterator<E, IteratorNode, &IteratorNode::previous, &IteratorNode::next, K> Iterator;
113
115 Tree() : root(0), nItems(0), m_Begin(0) {}
116
119 Tree(const Tree& x) : root(0), nItems(0), m_Begin(0) {
120 copyFrom(x);
121 }
122
125 clear();
126 delete m_Begin;
127 }
128
131 Tree& operator=(const Tree& x) {
132 if (this == &x)
133 return *this;
134
135 copyFrom(x);
136
137 return *this;
138 }
139
142 size_t count() const {
143 return nItems;
144 }
145
149 void insert(const K& key, const E& value) {
150 bool inserted = false;
151 Node* insertionNode = createInsertionNode(key, inserted);
152 insertionNode->element = value;
153 if (inserted)
154 ++nItems;
155 }
156
160 void insert(const K& key, E&& value) {
161 bool inserted = false;
162 Node* insertionNode = createInsertionNode(key, inserted);
163 insertionNode->element = pedigree_std::move(value);
164 if (inserted)
165 ++nItems;
166 }
167
169 bool tryInsert(const K& key, const E& value) {
170 bool inserted = false;
171 Node* node = createInsertionNode(key, inserted);
172 if (!node)
173 return false;
174 node->element = value;
175 if (inserted)
176 ++nItems;
177 return true;
178 }
179
180 bool tryInsert(const K& key, E&& value) {
181 bool inserted = false;
182 Node* node = createInsertionNode(key, inserted);
183 if (!node)
184 return false;
185 node->element = pedigree_std::move(value);
186 if (inserted)
187 ++nItems;
188 return true;
189 }
190
193 E lookup(const K& key) const {
194 Node* n = root;
195 while (n != 0) {
196 if (n->key == key)
197 return n->element;
198 else if (n->key > key)
199 n = n->leftChild;
200 else
201 n = n->rightChild;
202 }
203 return 0;
204 }
205
208 E* find(const K& key) {
209 Node* n = root;
210 while (n) {
211 if (n->key == key)
212 return &n->element;
213 if (n->key > key)
214 n = n->leftChild;
215 else
216 n = n->rightChild;
217 }
218 return nullptr;
219 }
220
223 const E& lookupRef(const K& key, const E& failed = E()) const {
224 Node* n = root;
225 while (n != 0) {
226 if (n->key == key)
227 return n->element;
228 else if (n->key > key)
229 n = n->leftChild;
230 else
231 n = n->rightChild;
232 }
233 return failed;
234 }
235
239 bool lowerBound(const K& key, K& foundKey, E& foundValue) const {
240 const Node* n = root;
241 const Node* bound = nullptr;
242 while (n) {
243 if (n->key == key) {
244 bound = n;
245 break;
246 } else if (n->key > key) {
247 bound = n;
248 n = n->leftChild;
249 } else {
250 n = n->rightChild;
251 }
252 }
253 if (!bound)
254 return false;
255
256 foundKey = bound->key;
257 foundValue = bound->element;
258 return true;
259 }
260
263 bool floorBound(const K& key, K& foundKey, E& foundValue) const {
264 const Node* n = root;
265 const Node* bound = nullptr;
266 while (n) {
267 if (n->key == key) {
268 bound = n;
269 break;
270 } else if (n->key > key) {
271 n = n->leftChild;
272 } else {
273 bound = n;
274 n = n->rightChild;
275 }
276 }
277 if (!bound)
278 return false;
279
280 foundKey = bound->key;
281 foundValue = bound->element;
282 return true;
283 }
284
287 bool contains(const K& key) const {
288 Node* n = root;
289 while (n != 0) {
290 if (n->key == key)
291 return true;
292 else if (n->key > key)
293 n = n->leftChild;
294 else
295 n = n->rightChild;
296 }
297 return false;
298 }
299
301 void remove(const K& key) {
302 Node* n = root;
303 while (n != 0) {
304 if (n->key == key)
305 break;
306 else if (n->key > key)
307 n = n->leftChild;
308 else
309 n = n->rightChild;
310 }
311
312 Node* orign = n;
313 if (n == 0)
314 return;
315
316 while (n->leftChild || n->rightChild) // While n is not a leaf.
317 {
318 size_t hl = height(n->leftChild);
319 size_t hr = height(n->rightChild);
320 if (hl == 0)
321 rotateLeft(n); // N is now a leaf.
322 else if (hr == 0)
323 rotateRight(n); // N is now a leaf.
324 else if (hl <= hr) {
325 rotateRight(n);
326 rotateLeft(n); // These are NOT inverse operations -
327 // rotateRight changes n's position.
328 } else {
329 rotateLeft(n);
330 rotateRight(n);
331 }
332 }
333
334 // N is now a leaf, so can be easily pruned.
335 if (n->parent == 0)
336 root = 0;
337 else {
338 if (n->parent->leftChild == n)
339 n->parent->leftChild = 0;
340 else
341 n->parent->rightChild = 0;
342 }
343
344 // Work our way up the path, balancing.
345 while (n) {
346 int b = balanceFactor(n);
347 if ((b < -1) || (b > 1))
348 rebalanceNode(n);
349 n = n->parent;
350 }
351
352 delete orign;
353 nItems--;
354 }
355
363 bool take(const K& key, E& element) {
364 Node* n = root;
365 while (n != 0) {
366 if (n->key == key)
367 break;
368 else if (n->key > key)
369 n = n->leftChild;
370 else
371 n = n->rightChild;
372 }
373
374 if (!n)
375 return false;
376
377 element = pedigree_std::move(n->element);
378 remove(key);
379 return true;
380 }
381
383 void clear() {
384 traverseNode_Remove(root);
385 root = 0;
386 nItems = 0;
387
388 delete m_Begin;
389 m_Begin = 0;
390 }
391
393 void erase(Iterator iter) {
394 // Remove the key from the tree.
395 remove(iter.key());
396
397 // Passed iterator is now invalid.
398 }
399
403 // If there is no node already, create a new one
404 if (!m_Begin)
405 m_Begin = new IteratorNode(root, 0, nItems);
406
407 // Reset the iterator node
408 else
409 m_Begin->reset(root, 0, nItems);
410 // m_Begin = new (static_cast<void*>(m_Begin)) IteratorNode(root, 0,
411 // nItems);
412
413 return Iterator(m_Begin);
414 }
418 if (!m_Begin)
419 m_Begin = new IteratorNode(root, 0, nItems);
420 else
421 m_Begin->reset(root, 0, nItems);
422
423 return ConstIterator(m_Begin);
424 }
428 return Iterator(0);
429 }
433 return ConstIterator(0);
434 }
435
436 private:
437 void copyFrom(const Tree& other) {
438 clear();
439 // Traverse the tree, adding everything encountered.
440 traverseNode_Insert(other.root);
441
442 if (m_Begin)
443 delete m_Begin;
444 m_Begin = new IteratorNode(root, 0, nItems);
445 }
446
447 void rotateLeft(Node* n) {
448 // See Cormen,Lieserson,Rivest&Stein pp-> 278 for pseudocode.
449 Node* y = n->rightChild; // Set Y.
450
451 n->rightChild = y->leftChild; // Turn Y's left subtree into N's right subtree.
452 if (y->leftChild != 0)
453 y->leftChild->parent = n;
454
455 y->parent = n->parent; // Link Y's parent to N's parent.
456 if (n->parent == 0)
457 root = y;
458 else if (n == n->parent->leftChild)
459 n->parent->leftChild = y;
460 else
461 n->parent->rightChild = y;
462 y->leftChild = n;
463 n->parent = y;
464 }
465
466 void rotateRight(Node* n) {
467 Node* y = n->leftChild;
468
469 n->leftChild = y->rightChild;
470 if (y->rightChild != 0)
471 y->rightChild->parent = n;
472
473 y->parent = n->parent;
474 if (n->parent == 0)
475 root = y;
476 else if (n == n->parent->leftChild)
477 n->parent->leftChild = y;
478 else
479 n->parent->rightChild = y;
480
481 y->rightChild = n;
482 n->parent = y;
483 }
484
485 size_t height(Node* n) {
486 // Assumes: n's children's heights are up to date. Will always be true
487 // if balanceFactor
488 // is called in a bottom-up fashion.
489 if (n == 0)
490 return 0;
491
492 size_t tempL = 0;
493 size_t tempR = 0;
494
495 if (n->leftChild != 0)
496 tempL = n->leftChild->height;
497 if (n->rightChild != 0)
498 tempR = n->rightChild->height;
499
500 tempL++; // Account for the height increase stepping up to us, its
501 // parent.
502 tempR++;
503
504 if (tempL > tempR) // If one is actually bigger than the other, return
505 // that, else return the other.
506 {
507 n->height = tempL;
508 return tempL;
509 } else {
510 n->height = tempR;
511 return tempR;
512 }
513 }
514
515 int balanceFactor(Node* n) {
516 return static_cast<int>(height(n->rightChild)) - static_cast<int>(height(n->leftChild));
517 }
518
519 void rebalanceNode(Node* n) {
520 // This way of choosing which rotation to do took me AGES to find...
521 // See
522 // http://www.cmcrossroads.com/bradapp/ftp/src/libs/C++/AvlTrees.html
523 int balance = balanceFactor(n);
524 if (balance < -1) // If it's left imbalanced, we need a right rotation.
525 {
526 if (balanceFactor(n->leftChild) > 0) // If its left child is right heavy...
527 {
528 // We need a RL rotation - left rotate n's left child, then
529 // right rotate N.
530 rotateLeft(n->leftChild);
531 rotateRight(n);
532 } else {
533 // RR rotation will do.
534 rotateRight(n);
535 }
536 } else if (balance > 1) {
537 if (balanceFactor(n->rightChild) < 0) // If its right child is left heavy...
538 {
539 // We need a LR rotation; Right rotate N's right child, then
540 // left rotate N.
541 rotateRight(n->rightChild);
542 rotateLeft(n);
543 } else {
544 // LL rotation.
545 rotateLeft(n);
546 }
547 }
548 }
549
550 void traverseNode_Insert(Node* n) {
551 if (!n)
552 return;
553 insert(n->key, n->element);
554 traverseNode_Insert(n->leftChild);
555 traverseNode_Insert(n->rightChild);
556 }
557
558 void traverseNode_Remove(Node* n) {
559 if (!n)
560 return;
561
562 Node* left = n->leftChild;
563 Node* right = n->rightChild;
564 n->leftChild = nullptr;
565 n->rightChild = nullptr;
566
567 traverseNode_Remove(left);
568 traverseNode_Remove(right);
569 delete n;
570 }
571
572 Node* createInsertionNode(const K& key, bool& inserted) {
573 inserted = false;
574 Node* parent = nullptr;
575 Node* current = root;
576 while (current) {
577 if (key == current->key)
578 return current;
579 parent = current;
580 current = key > current->key ? current->rightChild : current->leftChild;
581 }
582
583 Node* node = new Node;
584 if (!node)
585 return nullptr;
586 node->key = key;
587 node->parent = parent;
588 IteratorNode* beginning = m_Begin;
589 if (!beginning) {
590 beginning = new IteratorNode;
591 if (!beginning) {
592 delete node;
593 return nullptr;
594 }
595 }
596
597 // The node and iteration state are both admitted before linking anything.
598 m_Begin = beginning;
599 if (!parent) {
600 root = node;
601 m_Begin->reset(root, nullptr, 1);
602 } else if (key > parent->key) {
603 parent->rightChild = node;
604 } else {
605 parent->leftChild = node;
606 }
607 inserted = true;
608 while (parent) {
609 const int balance = balanceFactor(parent);
610 if (balance < -1 || balance > 1)
611 rebalanceNode(parent);
612 parent = parent->parent;
613 }
614 return node;
615 }
616
617 Node* root;
618 size_t nItems;
619
620 mutable IteratorNode* m_Begin;
621};
622
623// External specializations.
624extern template class Tree<void*, void*>; // IWYU pragma: keep
625extern template class Tree<int8_t, void*>; // IWYU pragma: keep
626extern template class Tree<int16_t, void*>; // IWYU pragma: keep
627extern template class Tree<int32_t, void*>; // IWYU pragma: keep
628extern template class Tree<int64_t, void*>; // IWYU pragma: keep
629extern template class Tree<uint8_t, void*>; // IWYU pragma: keep
630extern template class Tree<uint16_t, void*>; // IWYU pragma: keep
631extern template class Tree<uint32_t, void*>; // IWYU pragma: keep
632extern template class Tree<uint64_t, void*>; // IWYU pragma: keep
633extern template class Tree<int8_t, int8_t>; // IWYU pragma: keep
634extern template class Tree<int16_t, int16_t>; // IWYU pragma: keep
635extern template class Tree<int32_t, int32_t>; // IWYU pragma: keep
636extern template class Tree<int64_t, int64_t>; // IWYU pragma: keep
637extern template class Tree<uint8_t, uint8_t>; // IWYU pragma: keep
638extern template class Tree<uint16_t, uint16_t>; // IWYU pragma: keep
639extern template class Tree<uint32_t, uint32_t>; // IWYU pragma: keep
640extern template class Tree<uint64_t, uint64_t>; // IWYU pragma: keep
641
644#endif
An iterator applicable for many data structures.
Definition Iterator.h:147
A key/value dictionary.
Definition Tree.h:33
ConstIterator end() const
Definition Tree.h:432
E * find(const K &key)
Definition Tree.h:208
bool tryInsert(const K &key, const E &value)
Definition Tree.h:169
Iterator begin()
Definition Tree.h:402
Tree & operator=(const Tree &x)
Definition Tree.h:131
void remove(const K &key)
Definition Tree.h:301
bool contains(const K &key) const
Definition Tree.h:287
void erase(Iterator iter)
Definition Tree.h:393
bool lowerBound(const K &key, K &foundKey, E &foundValue) const
Definition Tree.h:239
Tree(const Tree &x)
Definition Tree.h:119
ConstIterator begin() const
Definition Tree.h:417
E lookup(const K &key) const
Definition Tree.h:193
void clear()
Definition Tree.h:383
void insert(const K &key, const E &value)
Definition Tree.h:149
const E & lookupRef(const K &key, const E &failed=E()) const
Definition Tree.h:223
Iterator::Const ConstIterator
Definition Tree.h:112
Tree()
Definition Tree.h:115
~Tree()
Definition Tree.h:124
bool floorBound(const K &key, K &foundKey, E &foundValue) const
Definition Tree.h:263
void insert(const K &key, E &&value)
Definition Tree.h:160
Iterator end()
Definition Tree.h:427
bool take(const K &key, E &element)
Definition Tree.h:363
size_t count() const
Definition Tree.h:142