diff --git a/include/ifaces/IIterator.h b/include/ifaces/IIterator.h index cc0f632..ea21be5 100644 --- a/include/ifaces/IIterator.h +++ b/include/ifaces/IIterator.h @@ -5,7 +5,6 @@ template class IIterator { public: - virtual T& operator*() const = 0; virtual T* operator->() const = 0; virtual operator const T*() const = 0; diff --git a/include/iterators/BFSIterator.h b/include/iterators/BFSIterator.h new file mode 100644 index 0000000..908e0c4 --- /dev/null +++ b/include/iterators/BFSIterator.h @@ -0,0 +1,42 @@ +#pragma once +#include + +#include "iterators/BaseIterator.h" + +template +class BFSIterator : public BaseIterator { +public: + explicit BFSIterator(T* ptr) : BaseIterator(ptr) { + if (!this->current) + return; + + for (auto& it : BaseIterator::current->children()) + q.push(it.get()); + } + + IIterator& operator++() override { + advance(); + return *this; + } + + virtual size_t level() const { + return level_; + } + +protected: + std::queue q; + size_t level_; + + void advance() { + if (q.empty()) { + this->current = nullptr; + return; + } + + this->current = q.front(); + q.pop(); + + for (auto& it : this->current->children()) + q.push(it.get()); + } +}; diff --git a/include/iterators/BaseIterator.h b/include/iterators/BaseIterator.h index 879f1aa..c9e1321 100644 --- a/include/iterators/BaseIterator.h +++ b/include/iterators/BaseIterator.h @@ -1,23 +1,43 @@ #pragma once +#include #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; } + struct Proxy { + T* e; + size_t level; + + T& operator*() const { return *e; } + T* operator->() const { return e; } + }; + + Proxy& operator*() { + proxy = Proxy{ current, this->level() }; + return proxy; + } + T* operator->() const override { return current; } - virtual operator const T*() const { return current; } + operator const T*() const { return current; } + operator T&() const { return *current; } + operator T*() const { return current; } bool operator!=(const IIterator& other) const override { const T* other_current = other; return current != other_current; } + +protected: + T* current; +private: + Proxy proxy; }; diff --git a/include/iterators/DFSIterator.h b/include/iterators/DFSIterator.h index 7732d78..06ae01a 100644 --- a/include/iterators/DFSIterator.h +++ b/include/iterators/DFSIterator.h @@ -1,17 +1,18 @@ #pragma once #include +#include #include "iterators/BaseIterator.h" template class DFSIterator : public BaseIterator { public: - explicit DFSIterator(T* ptr) : BaseIterator(ptr) { + explicit DFSIterator(T* ptr) : BaseIterator(ptr), level_(0) { if (!this->current) return; - for (auto& it : BaseIterator::current->children()) - s.push(it.get()); + for (auto it = BaseIterator::current->children().rbegin(); it != BaseIterator::current->children().rend(); ++it) + s.push({it->get(), 1}); } IIterator& operator++() override { @@ -22,8 +23,9 @@ public: virtual size_t level() const { return level_; } + protected: - std::stack s; + std::stack> s; size_t level_; void advance() { @@ -32,10 +34,14 @@ protected: return; } - this->current = s.top(); + auto [node, lvl] = s.top(); s.pop(); - for (auto& it : this->current->children()) - s.push(it.get()); + this->current = node; + level_ = lvl; + + for (auto it = this->current->children().rbegin(); + it != this->current->children().rend(); ++it) + s.push({it->get(), lvl + 1}); } }; diff --git a/include/iterators/Traversal.h b/include/iterators/Traversal.h new file mode 100644 index 0000000..a692c96 --- /dev/null +++ b/include/iterators/Traversal.h @@ -0,0 +1,22 @@ +#pragma once +#include + +#include "ifaces/INode.h" + +#include "iterators/DFSIterator.h" +#include "iterators/BFSIterator.h" + +template +class Traversal { + INode* start; + +public: + explicit Traversal(INode* start) : start(start) {} + explicit Traversal(NodePtr start) : start(start.get()) {} + + Policy begin() const { return Policy(start); } + Policy end() const { return Policy(nullptr); } +}; + +using TraversalDFS = Traversal>; +using TraversalBFS = Traversal>; diff --git a/src/main.cpp b/src/main.cpp index bafc0a3..582c419 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,32 +4,26 @@ #include "nodes/SimpleNode.h" #include "nodes/ComplexNode.h" -#include "iterators/DFSIterator.h" +#include "iterators/Traversal.h" -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) { +void printNode(INode& node, size_t level) { + for (size_t i = level; i > 0; i--) std::cout << " "; - parent = parent->parent(); - } std::cout << node.name() << "\n"; } -void printTree(INode& node) { - for (auto& child : Traversal>(&node)) - printNode(child); +void printTreeBFS(INode& node) { + for (auto& child : TraversalBFS(&node)) + printNode(*child, 0); +} +void printTreeList(INode& node) { + for (auto& child : TraversalDFS(&node)) + printNode(*child, 0); +} +void printTreeLadder(INode& node) { + for (auto& [child, level] : TraversalDFS(&node)) + printNode(*child, level); } int main() { @@ -47,7 +41,7 @@ int main() { root->linkChild(child1); std::cout << "\nInit tree:\n"; - printTree(*root); + printTreeLadder(*root); std::cout << "\n"; { @@ -99,21 +93,29 @@ int main() { } std::cout << "\nAnother tree:\n"; - printTree(*root); + printTreeLadder(*root); + std::cout << "\n"; + + std::cout << "\nList:\n"; + printTreeList(*root); + std::cout << "\n"; + + std::cout << "\nBFS:\n"; + printTreeBFS(*root); std::cout << "\n"; logger.info("Unlinking ComplexChild2...\n"); child2->unlinkParent(); std::cout << "\nTree after unlink:\n"; - printTree(*root); + printTreeLadder(*root); std::cout << "\n"; logger.info("Put refs of ComplexChild2, ComplexChild3 and its children"); } std::cout << "\nTree after scope out:\n"; - printTree(*root); + printTreeLadder(*root); std::cout << "\n"; logger.info("Unlinking ComplexChild1 and ComplexChild3...\n"); @@ -130,7 +132,7 @@ int main() { root->linkChild(child4); std::cout << "\nTree flush and link SimpleChild4:\n"; - printTree(*root); + printTreeLadder(*root); std::cout << "\n"; }