diff --git a/BFSIterator.h b/BFSIterator.h new file mode 100644 index 0000000..b17acf2 --- /dev/null +++ b/BFSIterator.h @@ -0,0 +1,21 @@ +#pragma once + +#include "iterators/BaseIterator.h" + +template +struct IteratorForward : public BaseIterator { + explicit IteratorForward(T* ptr) : Iterator(first(ptr)) {} + + static T* first(T* node) { + return node; + } + + static T* next(T* node) { + return node ? node->get_next() : nullptr; + } + + Iterator& operator++() override { + this->current = next(this->current); + return *this; + } +}; diff --git a/include/ifaces/IIterator.h b/include/ifaces/IIterator.h new file mode 100644 index 0000000..cc0f632 --- /dev/null +++ b/include/ifaces/IIterator.h @@ -0,0 +1,17 @@ +#pragma once + +/// \brief Интерфейс для классов-итераторов. +/// \tparam T Тип итерируемого элемента. +template +class IIterator { +public: + virtual T& operator*() const = 0; + virtual T* operator->() const = 0; + virtual operator const T*() const = 0; + + virtual bool operator!=(const IIterator& other) const = 0; + + virtual IIterator& operator++() = 0; + + virtual size_t level() const = 0; +}; diff --git a/include/ifaces/ILinkMixin.h b/include/ifaces/ILinkMixin.h index 67f3b6c..6ff21ab 100644 --- a/include/ifaces/ILinkMixin.h +++ b/include/ifaces/ILinkMixin.h @@ -14,5 +14,7 @@ public: virtual void linkChild(const ElemPtr& child) = 0; virtual void unlinkParent() = 0; virtual const std::vector& children() = 0; + virtual ElemPtr parent() = 0; virtual LinkPtr getLink() = 0; + //virtual operator ElemPtr() const = 0; }; diff --git a/include/iterators/BaseIterator.h b/include/iterators/BaseIterator.h new file mode 100644 index 0000000..879f1aa --- /dev/null +++ b/include/iterators/BaseIterator.h @@ -0,0 +1,23 @@ +#pragma once + +#include "ifaces/IIterator.h" + +/// \brief Базовый итератор. +/// \tparam T Тип итерируемого элемента. +/// Предоставляет базовую реализацию методов для работы с итерируемыми объектами. +template +class BaseIterator : public IIterator { +protected: + T* current; +public: + explicit BaseIterator(T* ptr) : current(ptr) {} + + T& operator*() const override { return *current; } + T* operator->() const override { return current; } + virtual operator const T*() const { return current; } + + bool operator!=(const IIterator& other) const override { + const T* other_current = other; + return current != other_current; + } +}; diff --git a/include/iterators/DFSIterator.h b/include/iterators/DFSIterator.h new file mode 100644 index 0000000..7732d78 --- /dev/null +++ b/include/iterators/DFSIterator.h @@ -0,0 +1,41 @@ +#pragma once +#include + +#include "iterators/BaseIterator.h" + +template +class DFSIterator : public BaseIterator { +public: + explicit DFSIterator(T* ptr) : BaseIterator(ptr) { + if (!this->current) + return; + + for (auto& it : BaseIterator::current->children()) + s.push(it.get()); + } + + IIterator& operator++() override { + advance(); + return *this; + } + + virtual size_t level() const { + return level_; + } +protected: + std::stack s; + size_t level_; + + void advance() { + if (s.empty()) { + this->current = nullptr; + return; + } + + this->current = s.top(); + s.pop(); + + for (auto& it : this->current->children()) + s.push(it.get()); + } +}; diff --git a/include/mixins/BaseLinkMixin.h b/include/mixins/BaseLinkMixin.h index 67ba4f6..8abc174 100644 --- a/include/mixins/BaseLinkMixin.h +++ b/include/mixins/BaseLinkMixin.h @@ -37,6 +37,13 @@ public: getLink()->setParent(nullptr); } + ElemPtr parent() override { + auto link = getLink(); + + ElemPtr parent = link->getParent(); + + return parent; + } const std::vector& children() override { auto link = getLink(); diff --git a/src/main.cpp b/src/main.cpp index 78b46eb..bafc0a3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,19 +1,35 @@ -#include "nodes/SimpleNode.h" -#include "nodes/ComplexNode.h" #include + #include "Logger.h" -void printTree(const NodePtr& node, int indent = 0) { - if (!node) { - Logger::get("MAIN").err("No node"); - return; - } +#include "nodes/SimpleNode.h" +#include "nodes/ComplexNode.h" +#include "iterators/DFSIterator.h" - for (int i = 0; i < indent; ++i) std::cout << " "; - std::cout << node->name() << "\n"; - for (const auto& child : node->children()) - printTree(child, indent + 1); +template +class Traversal { + INode* start; + +public: + explicit Traversal(INode* start) : start(start) {} + + Policy begin() const { return Policy(start); } + Policy end() const { return Policy(nullptr); } +}; + +void printNode(INode& node) { + NodePtr parent = node.parent(); + while (parent) { + std::cout << " "; + parent = parent->parent(); + } + std::cout << node.name() << "\n"; +} + +void printTree(INode& node) { + for (auto& child : Traversal>(&node)) + printNode(child); } int main() { @@ -31,7 +47,7 @@ int main() { root->linkChild(child1); std::cout << "\nInit tree:\n"; - printTree(root); + printTree(*root); std::cout << "\n"; { @@ -83,21 +99,21 @@ int main() { } std::cout << "\nAnother tree:\n"; - printTree(root); + printTree(*root); std::cout << "\n"; logger.info("Unlinking ComplexChild2...\n"); child2->unlinkParent(); std::cout << "\nTree after unlink:\n"; - printTree(root); + printTree(*root); std::cout << "\n"; logger.info("Put refs of ComplexChild2, ComplexChild3 and its children"); } std::cout << "\nTree after scope out:\n"; - printTree(root); + printTree(*root); std::cout << "\n"; logger.info("Unlinking ComplexChild1 and ComplexChild3...\n"); @@ -114,7 +130,7 @@ int main() { root->linkChild(child4); std::cout << "\nTree flush and link SimpleChild4:\n"; - printTree(root); + printTree(*root); std::cout << "\n"; }