From 912701ad923ea4e1379280b03cd72ba67d826a62 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Thu, 28 Jun 2018 21:21:36 +0200 Subject: [PATCH] document forward tree --- alib2std/src/extensions/forward_tree.hpp | 588 ++++++++++++++++++++++- 1 file changed, 582 insertions(+), 6 deletions(-) diff --git a/alib2std/src/extensions/forward_tree.hpp b/alib2std/src/extensions/forward_tree.hpp index 5e3616aad9..c4e006566a 100644 --- a/alib2std/src/extensions/forward_tree.hpp +++ b/alib2std/src/extensions/forward_tree.hpp @@ -1,6 +1,22 @@ /* * forward_tree.hpp * + * This file is part of Algorithms library toolkit. + * Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz) + + * Algorithms library toolkit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Algorithms library toolkit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with Algorithms library toolkit. If not, see <http://www.gnu.org/licenses/>. + * * Created on: Jul 2, 2016 * Author: Jan Travnicek */ @@ -20,25 +36,64 @@ namespace ext { +/** + * Class introducing a forward_tree with interface trying to be close to the interface of standard library containers. + * + * \tparam T the type of values inside nodes of the forward_tree + */ template < class T > class forward_tree { + /** + * \brief + * The value in the root node of the forward_tree + */ T m_data; + /** + * \brief + * Container of children of the root node of the tree. + * + * The children are forward_trees themselves, imitating the notion of a subtree of a tree is itself a tree + */ ext::vector < forward_tree > m_children; public: + /** + * \brief + * Getter of the value in the root node. + * + * \return the value in the root node + */ T & getData ( ) { return m_data; } + /** + * \brief + * Getter of the value in the root node. + * + * \return the value in the root node + */ const T & getData ( ) const { return m_data; } + /** + * \brief + * Getter of children of the root node. + * + * \return children of the root node + */ ext::vector < forward_tree > & getChildren ( ) { return m_children; } + /** + * \brief + * Getter of children of the root node. + * + * \return children of the root node + */ const ext::vector < forward_tree > & getChildren ( ) const { return m_children; } @@ -49,11 +104,35 @@ public: */ typedef typename ext::vector < forward_tree >::const_iterator const_children_iterator; + /** + * \brief + * The iterator type over structure of the tree representing nodes and node_ends + * + * The iterator performs a top to bottom, left to right or depth first travrsal stopping at each node twice. Once as it enters it the first time and second time when it leaves it (on the way to its parent). + */ class const_structure_iterator : public std::iterator < std::bidirectional_iterator_tag, T > { + /** + * \brief + * The underlying iterator within some list of children. + */ typename ext::vector < forward_tree >::const_iterator node; + + /** + * \brief + * List of references to parents so far visited. + */ typename ext::deque < const forward_tree * > parents; + /** + * \brief + * True if the iterator is pointing to a tree node in the first visit, false in the second (leaving case). + */ bool virtual_node; + + /** + * \brief + * True if the iterator is one position after the last valid iterator value. + */ bool isEnd; public: @@ -66,6 +145,12 @@ public: const_structure_iterator ( typename ext::vector < forward_tree >::const_iterator n ) : node ( n ), parents ( ), virtual_node ( false ), isEnd ( false ) { } + /** + * \brief + * Advance the iterator. + * + * \return the updated iterator + */ const_structure_iterator & operator ++( ) { if ( virtual_node ) { if ( parents.size ( ) ) { @@ -98,6 +183,12 @@ public: return * this; } + /** + * \brief + * Advance the iterator. + * + * \return the original iterator + */ const_structure_iterator operator ++( int ) { const_structure_iterator tmp ( * this ); @@ -105,6 +196,12 @@ public: return tmp; } + /** + * \brief + * Retract the iterator. + * + * \return the updated iterator + */ const_structure_iterator & operator --( ) { if ( isEnd ) { --node; @@ -137,6 +234,12 @@ public: return * this; } + /** + * \brief + * Retract the iterator. + * + * \return the original iterator + */ const_structure_iterator operator --( int ) { const_structure_iterator tmp ( * this ); @@ -144,26 +247,66 @@ public: return tmp; } + /** + * \brief + * Compare the iterators for equality. + * + * \brief other the other instance + * + * \return true if the two iterators are the same, false othervise + */ bool operator ==( const const_structure_iterator & other ) { return node == other.node && virtual_node == other.virtual_node; } + /** + * \brief + * Compare the iterators for nonequality. + * + * \brief other the other instance + * + * \return true if the two iterators are not the same, false othervise + */ bool operator !=( const const_structure_iterator & other ) { return !( * this == other ); } + /** + * \brief + * Dereference the iterator by accessing the pointed node value. + * + * \return the value of node pointed to + */ const T & operator *( ) const { return node->getData ( ); } + /** + * \brief + * Dereference the iterator by accessing the pointed node value. + * + * \return the value of node pointed to + */ const T * operator ->( ) const { return & node->getData ( ); } + /** + * \brief + * Retrieves what is the depth of node the iterator is pointing to. + * + * \return the depth of node pointed to + */ unsigned getLevel ( ) const { return parents.size ( ); } + /** + * \brief + * Allows to distinguis entry or leave visit of a pointed to node. + * + * \return true if the iterator is pointing to a tree node in the first visit, false in the second (leaving case). + */ bool getVirtual ( ) const { return virtual_node; } @@ -172,22 +315,47 @@ public: friend class forward_tree; }; + /** + * \brief + * The iterator type over structure of the tree following preorder traversal. + * + * The prefix iterator is constructed as a wrapper over structure iterator, it selects only non-virtual nodes. + */ class const_prefix_iterator : public std::iterator < std::bidirectional_iterator_tag, T > { + /** + * \brief + * The underlying structure iterator. + */ const_structure_iterator node; public: + /** + * \brief + * Constructor of the iterator based on the iterator to child list + * + * \param n the iterator to child list + */ const_prefix_iterator ( typename ext::vector < forward_tree >::const_iterator n ) : node ( n ) { } - const_prefix_iterator ( const const_prefix_iterator & other ) : node ( other.node ) { - } - + /** + * \brief + * Advance the iterator. + * + * \return the updated iterator + */ const_prefix_iterator & operator ++( ) { while ( ( ++node ).getVirtual ( ) ); return * this; } + /** + * \brief + * Advance the iterator. + * + * \return the original iterator + */ const_prefix_iterator operator ++( int ) { const_prefix_iterator tmp ( * this ); @@ -195,12 +363,24 @@ public: return tmp; } + /** + * \brief + * Retract the iterator. + * + * \return the updated iterator + */ const_prefix_iterator & operator --( ) { while ( ( --node ).getVirtual ( ) ); return * this; } + /** + * \brief + * Retract the iterator. + * + * \return the original iterator + */ const_prefix_iterator operator --( int ) { const_prefix_iterator tmp ( * this ); @@ -208,22 +388,56 @@ public: return tmp; } + /** + * \brief + * Compare the iterators for equality. + * + * \brief other the other instance + * + * \return true if the two iterators are the same, false othervise + */ bool operator ==( const const_prefix_iterator & other ) { return node == other.node; } + /** + * \brief + * Compare the iterators for nonequality. + * + * \brief other the other instance + * + * \return true if the two iterators are not the same, false othervise + */ bool operator !=( const const_prefix_iterator & other ) { return !( * this == other ); } + /** + * \brief + * Dereference the iterator by accessing the pointed node value. + * + * \return the value of node pointed to + */ const T & operator *( ) const { return * node; } + /** + * \brief + * Dereference the iterator by accessing the pointed node value. + * + * \return the value of node pointed to + */ const T * operator ->( ) const { return & node->getData ( ); } + /** + * \brief + * Retrieves what is the depth of node the iterator is pointing to. + * + * \return the depth of node pointed to + */ unsigned getLevel ( ) const { return node.getLevel ( ); } @@ -232,22 +446,47 @@ public: friend class forward_tree; }; + /** + * \brief + * The iterator type over structure of the tree following postorder traversal + * + * The prefix iterator is constructed as a wrapper over structure iterator, it selects only virtual nodes. + */ class const_postfix_iterator : public std::iterator < std::bidirectional_iterator_tag, T > { + /** + * \brief + * The underlying structure iterator. + */ const_structure_iterator node; public: + /** + * \brief + * Constructor of the iterator based on the iterator to child list + * + * \param n the iterator to child list + */ const_postfix_iterator ( typename ext::vector < forward_tree >::const_iterator n ) : node ( n ) { } - const_postfix_iterator ( const const_postfix_iterator & other ) : node ( other.node ) { - } - + /** + * \brief + * Advances the iterator. + * + * \return the updated iterator + */ const_postfix_iterator & operator ++( ) { while ( !( ++node ).getVirtual ( ) && !node.isEnd ); return * this; } + /** + * \brief + * Advances the iterator. + * + * \return the original iterator + */ const_postfix_iterator operator ++( int ) { const_postfix_iterator tmp ( * this ); @@ -255,12 +494,24 @@ public: return tmp; } + /** + * \brief + * Retract the iterator. + * + * \return the updated iterator + */ const_postfix_iterator & operator --( ) { while ( !( --node ).getVirtual ( ) ); return * this; } + /** + * \brief + * Retract the iterator. + * + * \return the original iterator + */ const_postfix_iterator operator --( int ) { const_postfix_iterator tmp ( * this ); @@ -268,22 +519,56 @@ public: return tmp; } + /** + * \brief + * Compare the iterators for equality. + * + * \brief other the other instance + * + * \return true if the two iterators are the same, false othervise + */ bool operator ==( const const_postfix_iterator & other ) { return node == other.node; } + /** + * \brief + * Compare the iterators for nonequality. + * + * \brief other the other instance + * + * \return true if the two iterators are not the same, false othervise + */ bool operator !=( const const_postfix_iterator & other ) { return !( * this == other ); } + /** + * \brief + * Dereference the iterator by accessing the pointed node value. + * + * \return the value of node pointed to + */ const T & operator *( ) const { return * node; } + /** + * \brief + * Dereference the iterator by accessing the pointed node value. + * + * \return the value of node pointed to + */ const T * operator ->( ) const { return & node->getData ( ); } + /** + * \brief + * Retrieves what is the depth of node the iterator is pointing to. + * + * \return the depth of node pointed to + */ unsigned getLevel ( ) const { return node.getLevel ( ); } @@ -317,12 +602,32 @@ private: } public: + /** + * \brief + * Inserts a subtree into a forward_tree. + * + * \param under the node under which to add the subtree + * \param position the specification of position in children of the node where to add subtrees + * \param value a subtree to insert + * + * \return updated position iterator pointing to the first node inserted + */ const_children_iterator insert ( const_children_iterator under, const_children_iterator position, forward_tree < T > && value ) { ext::vector < forward_tree > & children = const_cast < ext::vector < forward_tree > & > ( under->getChildren ( ) ); return children.insert ( position, std::move ( value ) ); } + /** + * \brief + * Inserts a subtree into a forward_tree. + * + * \param under the node under which to add the subtree + * \param position the specification of position in children of the node where to add subtrees + * \param value a subtree to insert + * + * \return updated position iterator pointing to the first node inserted + */ const_children_iterator insert ( const_children_iterator under, const_children_iterator position, const forward_tree < T > & value ) { return insert ( under, position, forward_tree < T > ( value ) ); } @@ -376,44 +681,111 @@ public: forward_tree ( T && data, ext::vector < forward_tree > && children ) : m_data ( std::move ( data ) ), m_children ( std::move ( children ) ) { } + /** + * \brief + * Constructor of the forward_tree from value to be stored in the root node and children trees. + * + * \param data the value to be stored in the root + * \param children list of subtrees + */ forward_tree ( const T & data, const ext::vector < forward_tree > & subtrees ) : forward_tree ( T ( data ), ext::vector < forward_tree > ( subtrees ) ) { } + /** + * \brief + * Constructor of the forward_tree from value to be stored in the root node and pack of children trees. + * + * \param data the value to be stored in the root + * \param subtrees ... pack of subtrees + */ template < typename ... Types > forward_tree ( const T & data, Types ... subtrees ) : forward_tree ( data, ext::vector < forward_tree > { subtrees ... } ) { } + /** + * \brief + * Constructor of the forward_tree from value to be stored in the root node and pack of children trees. + * + * \param data the value to be stored in the root + * \param subtrees ... pack of subtrees + */ template < typename ... Types > forward_tree ( T && data, Types ... subtrees ) : forward_tree ( std::move ( data ), ext::vector < forward_tree > { subtrees ... } ) { } + /** + * \brief + * Constructor of the forward_tree from value to be stored in the root node and range of values to construct nullary nodes from range of values. + * + * \param data the value to be stored in the root + * \param begin the iterator to the begining of values range + * \param end the iterator to the end of values range + */ template < typename Iterator, typename std::enable_if < ext::is_iterator < Iterator >::value >::type > forward_tree ( const T & data, Iterator begin, Iterator end ) : forward_tree ( data, fromIterator ( begin, end ) ) { } + /** + * \brief + * Constructor of the forward_tree from value to be stored in the root node and range of subtrees. + * + * \param data the value to be stored in the root + * \param begin the iterator to the begining of subtree range + * \param end the iterator to the end of subtree range + */ forward_tree ( const T & data, const_children_iterator begin, const_children_iterator end ) : forward_tree ( data, ext::vector < forward_tree > ( begin, end ) ) { } // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + /** + * \brief + * Getter of a children iterator to the root of the tree + * + * \return iterator to the root + */ const_children_iterator root ( ) const { return typename ext::vector < forward_tree >::const_iterator ( this ); } + /** + * \brief + * Getter of a children iterator to the begining of children + * + * \return iterator to the first child + */ const_children_iterator begin ( ) const { return m_children.begin ( ); } + /** + * \brief + * Getter of a children iterator one after the last child + * + * \return iterator one after the last child + */ const_children_iterator end ( ) const { return m_children.end ( ); } // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + /** + * \brief + * Getter of the prefix iterator to the root node + * + * \return prefix iterator to the root + */ const_prefix_iterator prefix_begin ( ) const { return typename ext::vector < forward_tree >::const_iterator ( this ); } + /** + * \brief + * Getter of the prefix iterator one after the last node in the prefix traversal + * + * \return prefix iterator one after the last node in the prefix traversal + */ const_prefix_iterator prefix_end ( ) const { const_prefix_iterator res ( typename ext::vector < forward_tree >::const_iterator ( this + 1 ) ); @@ -423,6 +795,12 @@ public: // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + /** + * \brief + * Getter of the postfix iterator to the first node in the postfix traversal + * + * \return prefix iterator to the first node in the postfix traversal + */ const_postfix_iterator postfix_begin ( ) const { const_postfix_iterator res { typename ext::vector < forward_tree >::const_iterator ( this ) }; @@ -431,6 +809,12 @@ public: return res; } + /** + * \brief + * Getter of the postfix iterator one after the last node in the postfix traversal + * + * \return prefix iterator one after the last node in the postfix traversal + */ const_postfix_iterator postfix_end ( ) const { const_postfix_iterator res ( typename ext::vector < forward_tree >::const_iterator ( this + 1 ) ); @@ -440,10 +824,22 @@ public: // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + /** + * \brief + * Getter of the structure iterator to the first node in the traversal + * + * \return prefix iterator to the first node in the traversal + */ const_structure_iterator structure_begin ( ) const { return typename ext::vector < forward_tree >::const_iterator ( this ); } + /** + * \brief + * Getter of the structure iterator to one after the last node in the traversal + * + * \return prefix iterator to one after the last node in the traversal + */ const_structure_iterator structure_end ( ) const { const_structure_iterator res ( typename ext::vector < forward_tree >::const_iterator ( this + 1 ) ); @@ -453,26 +849,61 @@ public: // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + /** + * \brief + * Pushbacks a subtree after last child of a node specified by an interator given by \p under. + * + * \param under the node under which to add the subtree + * \param value a subtree to pushback to child list + */ void push_back ( const_children_iterator under, ext::forward_tree < T > && value ) { ext::vector < forward_tree > & children = const_cast < ext::vector < forward_tree > & > ( under->getChildren ( ) ); children.push_back ( std::move ( value ) ); } + /** + * \brief + * Pushbacks a subtree after last child of a node specified by an interator given by \p under. + * + * \param under the node under which to add the subtree + * \param value a subtree to pushback to child list + */ void push_back ( const_children_iterator under, const ext::forward_tree < T > & value ) { push_back ( under, forward_tree ( value ) ); } + /** + * \brief + * Pushbacks a nullary node after last child of a node specified by an interator given by \p under. + * + * \param under the node under which to add the subtree + * \param value a value to store in nullary node push-backed to the child list + */ void push_back ( const_children_iterator under, T && value ) { push_back ( under, forward_tree ( std::move ( value ) ) ); } + /** + * \brief + * Pushbacks a nullary node after last child of a node specified by an interator given by \p under. + * + * \param under the node under which to add the subtree + * \param value a value to store in nullary node push-backed to the child list + */ void push_back ( const_children_iterator under, const T & value ) { push_back ( under, T ( value ) ); } // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + /** + * \brief + * Erases a subtree from a tree on given by \p position under a node from \p under + * + * \param under the node under which to perform the erase + * \param position the specification of position in children where to erase the subtree + */ const_children_iterator erase ( const_children_iterator under, const_children_iterator position ) { ext::vector < forward_tree > & children = const_cast < ext::vector < forward_tree > & > ( under->getChildren ( ) ); @@ -481,11 +912,29 @@ public: // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + /** + * \brief + * Access value given indexes of chindren allong the selection path + * + * \tparam Indexes ... types of child indexes + * + * \param indexes actual values of child indexes + * + * \return the value in the selected node + */ template < class ... Indexes > const T & operator ()( Indexes ... indexes ) const { return this->operator ()( { ( unsigned ) indexes ... } ); } + /** + * \brief + * Access value given indexes of chindren allong the selection path + * + * \param indexes actual values of child indexes + * + * \return the value in the selected node + */ const T & operator ()( std::initializer_list < unsigned > indexes ) const { const forward_tree * node = this; @@ -496,11 +945,29 @@ public: return node->getData ( ); } + /** + * \brief + * Access value given indexes of chindren allong the selection path + * + * \tparam Indexes ... types of child indexes + * + * \param indexes actual values of child indexes + * + * \return the value in the selected node + */ template < class ... Indexes > T & operator ()( Indexes ... indexes ) { return this->operator ()( { ( unsigned ) indexes ... } ); } + /** + * \brief + * Access value given indexes of chindren allong the selection path + * + * \param indexes actual values of child indexes + * + * \return the value in the selected node + */ T & operator ()( std::initializer_list < unsigned > indexes ) { forward_tree * node = this; @@ -513,6 +980,13 @@ public: // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + /** + * \brief + * Swap method of two forward trees + * + * \param first the first forward tree to swap + * \param second the second forward tree to swap + */ friend void swap ( forward_tree & first, forward_tree & second ) { using std::swap; @@ -522,6 +996,16 @@ public: // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + /** + * \brief + * Three-way comparison method of forward trees. + * + * \param other the other instance to compare against + * + * \return negative if this instance is smaller than \p other instance + * zero if this is equal to \p other instance + * positive if this instance is bigger than \p other instance + */ int compare ( const forward_tree & other ) const { static ext::compare < typename std::decay < T >::type > comp; auto iterF = this->prefix_begin ( ); @@ -540,32 +1024,102 @@ public: return 0; } + /** + * \brief + * Equality comparison operator. + * + * \param other the other instance to compare with + * + * \return true if this instance is equal to other instance, false othervise + */ bool operator ==( const forward_tree & other ) { return compare ( other ) == 0; } + /** + * \brief + * Non-equality comparison operator. + * + * \param other the other instance to compare with + * + * \return true if this instance is not equal to other instance, false othervise + */ bool operator !=( const forward_tree & other ) { return compare ( other ) != 0; } + /** + * \brief + * Less comparison operator. + * + * \param other the other instance to compare with + * + * \return true if this instance is smaller than other instance, false othervise + */ bool operator <( const forward_tree & other ) { return compare ( other ) < 0; } + /** + * \brief + * Less or equal comparison operator. + * + * \param other the other instance to compare with + * + * \return true if this instance is smaller or equal than other instance, false othervise + */ bool operator <=( const forward_tree & other ) { return compare ( other ) <= 0; } + /** + * \brief + * Greater comparison operator. + * + * \param other the other instance to compare with + * + * \return true if this instance is greater than other instance, false othervise + */ bool operator >( const forward_tree & other ) { return compare ( other ) > 0; } + /** + * \brief + * Greater or equal comparison operator. + * + * \param other the other instance to compare with + * + * \return true if this instance is greater or equal than other instance, false othervise + */ bool operator >=( const forward_tree & other ) { return compare ( other ) >= 0; } // ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + /** + * \brief + * Internal method of printing a tree into a stream + * + * The tree is printed hierarchically. + * + * Example tree a ( b ( c ), b ( c ) ) would be printed like + * + * \-a + * | + * |-b + * | | + * | \-c + * | + * \-b + * | + * \-c + * + * \param os the stream to print to + * + * \return the changed output stream + */ std::ostream & nicePrint ( std::ostream & os ) const { nicePrint ( os, "", true ); return os; @@ -614,6 +1168,16 @@ private: } }; +/** + * Operator to print the forward_tree to the output stream. + * + * \param out the output stream + * \param forward_tree the forward_tree to print + * + * \tparam T the type of values inside the forward_tree + * + * \return the output stream from the \p out + */ template < class T > std::ostream & operator <<( std::ostream & out, const forward_tree < T > & t ) { out << "["; @@ -645,6 +1209,11 @@ std::ostream & operator <<( std::ostream & out, const forward_tree < T > & t ) { return out; } +/** + * Specialisation of the compare structure implementing the three-way comparison + * + * \tparam T the type of values inside the forward_tree + */ template < class T > struct compare < ext::forward_tree < T > > { int operator ()( const ext::forward_tree < T > & first, const ext::forward_tree < T > & second ) const { @@ -653,6 +1222,13 @@ struct compare < ext::forward_tree < T > > { }; +/** + * Overload of to_string function. + * + * \param value the forward_tree to be converted to string + * + * \tparam T the type of values inside the forward_tree + */ template < class T > std::string to_string ( const ext::forward_tree < T > & value ) { std::stringstream ss; -- GitLab