Kale
Loading...
Searching...
No Matches
Tree.hpp
Go to the documentation of this file.
1/*
2 Copyright 2022 Rishi Challa
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#pragma once
18
19#include <list>
20#include <iterator>
21#include <algorithm>
22#include <memory>
23
24namespace Kale {
25
30 template <typename T> class Tree {
31 public:
32
36 struct Child {
37 private:
38
42 Child* next = nullptr;
43
47 Child* previous = nullptr;
48
52 Child* parent = nullptr;
53
58
62 std::list<Child> children;
63
67 size_t horizontal;
68
72 size_t vertical;
73
78
82 void setup() {
83 // Create a pointer/iterator to use for misc searching purposes
84 Child* it = nullptr;
85
86 // Find the next child
87 it = parent->next;
88 while (it != nullptr) {
89 if (!it->children.empty()) {
90 next = &it->children.front();
91 break;
92 }
93 it = it->next;
94 }
95
96 // Find the previous child
97 if (next != nullptr) previous = next->previous;
98 else {
99 it = parent;
100 while (it != nullptr) {
101 if (!it->children.empty()) {
102 previous = &it->children.back();
103 break;
104 }
105 it = it->previous;
106 }
107 }
108
109 // Update the next/previous of surrounding children
110 if (next != nullptr) next->previous = this;
111 if (previous != nullptr) previous->next = this;
112
113 // Set the horizontal & vertical indices based on the next/previous/parent
114 horizontal = previous != nullptr ? previous->getHorizontalIndex() + 1 : 0;
115 vertical = parent->vertical + 1;
116
117 // Update the back if applicable
119 tree.backPtr = this;
120
121 // All children on the same vertical level with greater horizontal indices need to be updated
122 it = next;
123 while (it != nullptr) {
124 it->horizontal++;
125 it = it->next;
126 }
127 }
128
129 friend class Tree<T>;
130
131 public:
132
139
147
156
164 setup();
165 }
166
171 if (previous != nullptr) previous->next = next;
172 if (next != nullptr) next->previous = previous;
173
174 Child* it = next;
175 while (it != nullptr) {
176 it->horizontal--;
177 it = it->next;
178 }
179 }
180
181 // Deleting moving/copying
182 Child(const Child& other) = delete;
183 Child(Child&& other) = delete;
184 void operator=(const Child& other) = delete;
185 void operator=(Child&& other) = delete;
186
191 return children.emplace_back(*this);
192 }
193
199 return children.emplace_back(*this, value);
200 }
201
206 void removeChild(size_t horizontal) {
207 children.remove_if([&](const Child& child) { return child.getHorizontalIndex() == horizontal; });
208 }
209
214 const T* operator->() const {
215 return &value;
216 }
217
223 return &value;
224 }
225
230 const T& getValue() const {
231 return value;
232 }
233
239 return value;
240 }
241
246 const Child* getNext() const {
247 return next;
248 }
249
255 return next;
256 }
257
262 const Child* getPrevious() const {
263 return previous;
264 }
265
271 return previous;
272 }
273
278 const Child* getParent() const {
279 return parent;
280 }
281
287 return parent;
288 }
289
294 size_t getHorizontalIndex() const {
295 return horizontal;
296 }
297
302 size_t getVerticalIndex() const {
303 return vertical;
304 }
305
310 const std::list<Child>& getChildren() const {
311 return children;
312 }
313
318 std::list<Child>& getChildren() {
319 return children;
320 }
321
322 };
323
328 template <typename S> struct RawIterator {
329 private:
330
335
339 const Tree& tree;
340
341 public:
342
343 // Required information for custom iterators
344 using iterator_category = std::bidirectional_iterator_tag;
345 using value_type = S;
346 using pointer = S*;
347 using reference = S&;
348
354 RawIterator(const Tree& tree, S* ptr = nullptr) : tree(tree), ptr(ptr) {}
355
361 RawIterator<S>& operator=(S* ptr) { this->ptr = ptr; }
362
367 operator bool() const { return ptr != nullptr; }
368
374 bool operator==(const RawIterator<S> it) const { return it.ptr == ptr; }
375
381 bool operator!=(const RawIterator<S> it) const { return it.ptr != ptr; }
382
388 // The next isn't nullptr, we simply move on to the next in the same horizontal index
389 if (ptr->getNext() != nullptr) {
390 ptr = ptr->getNext();
391 return *this;
392 }
393
394 // We need to move to the next vertical index, keep searching the previous nodes for children
395 // If found, set it so we get the earliest one possible.
396 S* it = ptr;
397 ptr = nullptr;
398 while (it != nullptr) {
399 if (!it->getChildren().empty()) ptr = &it->getChildren().front();
400 it = it->getPrevious();
401 }
402
403 // If ptr is nullptr, it means we've finished looping (this iterator is now the end)
404 return *this;
405 }
406
412 if (ptr == nullptr) {
413 ptr = tree.backPtr;
414 return *this;
415 }
416
417 // This is the root, it can't be decremented
418 if (ptr->getParent() == nullptr) return *this;
419
420 // The previous isn't nullptr, we simply move on to the previous in the same horizontal index
421 if (ptr->getPrevious() != nullptr) {
422 ptr = ptr->getPrevious();
423 return *this;
424 }
425
426 // We need to move to the previous vertical index, go to our parent then go to the last index possible
427 ptr = ptr->getParent();
428 while (ptr->getNext() != nullptr) ptr = ptr->getNext();
429
430 // If ptr is nullptr, it means we've finished looping (this iterator is now the beginning)
431 return *this;
432 }
433
439 RawIterator<S> it = *this;
440 ++(*this);
441 return it;
442 }
443
449 RawIterator<S> it = *this;
450 --(*this);
451 return it;
452 }
453
459 return *ptr;
460 }
461
466 const S& operator*() const {
467 return *ptr;
468 }
469
475 return ptr;
476 }
477
482 const S* operator->() const {
483 return ptr;
484 }
485
490 S* getPtr() const {
491 return ptr;
492 }
493
498 const S* getConstPtr() const {
499 return ptr;
500 }
501 };
502
503 private:
504
509
510 friend struct Child;
511 friend struct RawIterator<Child>;
512 friend struct RawIterator<const Child>;
513
514 public:
515
520
525
529 std::unique_ptr<Child> root;
530
534 Tree() : root(std::make_unique(*this)), backPtr(&root) {}
535
540 Tree(const T& value) : root(std::make_unique(*this, value)), backPtr(&root) {}
541
542 // Tree(const Tree& other);
543 // void operator=(const Tree& other);
544
545 // Trees don't support moving
546 Tree(Tree&& other) = delete;
547 void operator=(Tree&& other) = delete;
548
554 return Iterator(*this, &root);
555 }
556
562 return ConstIterator(*this, &root);
563 }
564
570 return Iterator(*this, nullptr);
571 }
572
578 return ConstIterator(*this, nullptr);
579 }
580
581
587 return *root;
588 }
589
594 const Child& front() const {
595 return *root;
596 }
597
603 return *backPtr;
604 }
605
610 const Child& back() const {
611 return *backPtr;
612 }
613
620 const Child& operator()(size_t horizontal, size_t vertical) const {
621 return *std::find_if(cbegin(), cend(), [&](const Child& child) {
622 return child.getHorizontalIndex() == horizontal && child.getVerticalIndex() == vertical;
623 });
624 }
625
632 Child& operator()(size_t horizontal, size_t vertical) {
633 return *std::find_if(begin(), end(), [&](const Child& child) {
634 return child.getHorizontalIndex() == horizontal && child.getVerticalIndex() == vertical;
635 });
636 }
637
638 };
639
640}
Iterator begin()
Definition Tree.hpp:553
Child & front()
Definition Tree.hpp:586
Tree(const T &value)
Definition Tree.hpp:540
RawIterator< const Child > ConstIterator
Definition Tree.hpp:524
Tree(Tree &&other)=delete
Child & back()
Definition Tree.hpp:602
Child * backPtr
Definition Tree.hpp:508
void operator=(Tree &&other)=delete
const Child & front() const
Definition Tree.hpp:594
RawIterator< Child > Iterator
Definition Tree.hpp:519
Iterator end()
Definition Tree.hpp:569
std::unique_ptr< Child > root
Definition Tree.hpp:529
const Child & operator()(size_t horizontal, size_t vertical) const
Definition Tree.hpp:620
Child & operator()(size_t horizontal, size_t vertical)
Definition Tree.hpp:632
const Child & back() const
Definition Tree.hpp:610
ConstIterator cbegin() const
Definition Tree.hpp:561
ConstIterator cend() const
Definition Tree.hpp:577
const Child * getPrevious() const
Definition Tree.hpp:262
void operator=(const Child &other)=delete
void removeChild(size_t horizontal)
Definition Tree.hpp:206
std::list< Child > & getChildren()
Definition Tree.hpp:318
Child * parent
Definition Tree.hpp:52
Child(const Child &other)=delete
const Child * getNext() const
Definition Tree.hpp:246
Child * previous
Definition Tree.hpp:47
size_t getVerticalIndex() const
Definition Tree.hpp:302
Child * getPrevious()
Definition Tree.hpp:270
void operator=(Child &&other)=delete
Child(Child &parent)
Definition Tree.hpp:153
Child(Child &&other)=delete
const Child * getParent() const
Definition Tree.hpp:278
Child & addChild()
Definition Tree.hpp:190
size_t getHorizontalIndex() const
Definition Tree.hpp:294
Child * next
Definition Tree.hpp:42
const T * operator->() const
Definition Tree.hpp:214
Child * getParent()
Definition Tree.hpp:286
size_t horizontal
Definition Tree.hpp:67
std::list< Child > children
Definition Tree.hpp:62
size_t vertical
Definition Tree.hpp:72
Child(Child &parent, const T &value)
Definition Tree.hpp:163
const T & getValue() const
Definition Tree.hpp:230
Child & addChild(const T &value)
Definition Tree.hpp:198
Child(Tree &tree, const T &value)
Definition Tree.hpp:146
Child(Tree &tree)
Definition Tree.hpp:138
Child * getNext()
Definition Tree.hpp:254
const std::list< Child > & getChildren() const
Definition Tree.hpp:310
const Tree & tree
Definition Tree.hpp:339
bool operator==(const RawIterator< S > it) const
Definition Tree.hpp:374
const S * getConstPtr() const
Definition Tree.hpp:498
RawIterator< S > & operator++()
Definition Tree.hpp:387
RawIterator< S > & operator--()
Definition Tree.hpp:411
bool operator!=(const RawIterator< S > it) const
Definition Tree.hpp:381
const S & operator*() const
Definition Tree.hpp:466
RawIterator(const Tree &tree, S *ptr=nullptr)
Definition Tree.hpp:354
RawIterator< S > operator++(int)
Definition Tree.hpp:438
S * getPtr() const
Definition Tree.hpp:490
const S * operator->() const
Definition Tree.hpp:482
RawIterator< S > & operator=(S *ptr)
Definition Tree.hpp:361
RawIterator< S > operator--(int)
Definition Tree.hpp:448
std::bidirectional_iterator_tag iterator_category
Definition Tree.hpp:344