Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/gen/nary_tree.h

Go to the documentation of this file.
00001 //  Copyright (C) 2001--2002  Petter Urkedal
00002 //
00003 //  This file is free software; you can redistribute it and/or modify
00004 //  it under the terms of the GNU General Public License as published by
00005 //  the Free Software Foundation; either version 2 of the License, or
00006 //  (at your option) any later version.
00007 //
00008 //  This file is distributed in the hope that it will be useful,
00009 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 //  GNU General Public License for more details.
00012 //
00013 //  You should have received a copy of the GNU General Public License
00014 //  along with this program; if not, write to the Free Software
00015 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016 //
00017 //  As a special exception, you may use this file as part of a free
00018 //  software library without restriction.  Specifically, if other files
00019 //  instantiate templates or use macros or inline functions from this
00020 //  file, or you compile this file and link it with other files to
00021 //  produce an executable, this file does not by itself cause the
00022 //  resulting executable to be covered by the GNU General Public
00023 //  License.  This exception does not however invalidate any other
00024 //  reasons why the executable file might be covered by the GNU General
00025 //  Public License.
00026 //
00027 //  $Id: nary_tree.h,v 1.2 2002/08/24 13:58:38 petter_urkedal Exp $
00028 
00029 
00030 #ifndef MORE_GEN_NARY_TREE_H
00031 #define MORE_GEN_NARY_TREE_H
00032 
00033 #include <iterator>
00034 #include <stdexcept>
00035 #include <algorithm>
00036 #include <more/gen/memory.h>
00037 #include <more/gen/utility.h>
00038 
00039 
00040 namespace more {
00041 namespace gen {
00042 
00043   using std::swap;
00044 
00045   ///\if bits
00046   namespace bits {
00047     struct _nary_tree_node_base : noncopyable
00048     {
00049         typedef _nary_tree_node_base self;
00050         _nary_tree_node_base()
00051             : m_prev(this), m_next(this), m_parent(0) {}
00052 
00053         self*           prev()          { return m_prev; }
00054         self const*     prev() const    { return m_prev; }
00055         self*           next()          { return m_next; }
00056         self const*     next() const    { return m_next; }
00057 
00058         void unlink()
00059         {
00060             m_prev->m_next = m_next;
00061             m_next->m_prev = m_prev;
00062             m_parent = 0;
00063         }
00064 
00065         self* m_prev;
00066         self* m_next;
00067         self* m_parent;
00068     };
00069   }
00070   ///\endif
00071 
00072   struct tree_iterator_tag : std::bidirectional_iterator_tag {};
00073 
00074   template<typename T, typename Allocator> class nary_tree;
00075 
00076   ///\if bits
00077   namespace bits {
00078     template<typename T> class _nary_tree_node;
00079     template<typename T> class _nary_tree_iterator;
00080     template<typename T> class _const_nary_tree_iterator;
00081 
00082     template<typename Node>
00083       struct _nary_tree_iterator
00084       {
00085         private:
00086           typedef _nary_tree_iterator self;
00087         public:
00088           typedef tree_iterator_tag iterator_category;
00089           typedef typename Node::value_type value_type;
00090           typedef ptrdiff_t difference_type;
00091           typedef typename Node::iterator iterator;
00092           typedef typename Node::const_iterator const_iterator;
00093           typedef value_type& reference;
00094           typedef value_type const& const_reference;
00095           typedef value_type* pointer;
00096 
00097           _nary_tree_iterator() : m_cur(0) {}
00098           _nary_tree_iterator(_nary_tree_iterator const& it)
00099               : m_cur(it.m_cur) {}
00100           _nary_tree_iterator(_nary_tree_node_base* n) : m_cur(n) {}
00101           _nary_tree_iterator(_nary_tree_node_base const* n) : m_cur(n) {}
00102           _nary_tree_iterator& operator=(_nary_tree_iterator const& it)
00103           { m_cur = it.m_cur; return *this; }
00104 
00105           bool operator==(_nary_tree_iterator const& it) const
00106           { return m_cur == it.m_cur; }
00107           bool operator!=(_nary_tree_iterator const& it) const
00108           { return m_cur != it.m_cur; }
00109 
00110           _nary_tree_iterator& operator++()
00111           { m_cur = m_cur->next(); return *this; }
00112           _nary_tree_iterator operator++(int)
00113           { _nary_tree_iterator tmp = *this; ++*this; return tmp; }
00114           _nary_tree_iterator& operator--()
00115           { m_cur = m_cur->prev(); return *this; }
00116           _nary_tree_iterator operator--(int)
00117           { _nary_tree_iterator tmp = *this; --*this; return tmp; }
00118 
00119           self begin() { return static_cast<Node*>(m_cur)->begin(); }
00120           self end() { return static_cast<Node*>(m_cur)->end(); }
00121           bool empty() { return begin() == end(); }
00122 
00123           self parent()
00124           {
00125               if (!m_cur->m_parent)
00126                   throw std::logic_error("_nary_tree_iterator::parent(): "
00127                                          "Root node has no parent.");
00128               return static_cast<Node*>(m_cur)->parent();
00129           }
00130 
00131           reference operator*() { return static_cast<Node*>(m_cur)->value; }
00132           pointer operator->() { return &static_cast<Node*>(m_cur)->value; }
00133 
00134         private:
00135           _nary_tree_node_base* m_cur;
00136 
00137           friend class _nary_tree_node<value_type>;
00138           template<typename U, typename Allocator> friend class nary_tree;
00139           friend class _const_nary_tree_iterator<Node>;
00140       };
00141 
00142     template<typename Node>
00143       struct _const_nary_tree_iterator
00144       {
00145           typedef _const_nary_tree_iterator self;
00146           typedef tree_iterator_tag iterator_category;
00147           typedef const typename Node::value_type value_type;
00148           typedef ptrdiff_t difference_type;
00149           typedef typename Node::iterator iterator;
00150           typedef typename Node::const_iterator const_iterator;
00151           typedef value_type& reference;
00152           typedef value_type const& const_reference;
00153           typedef value_type* pointer;
00154 
00155           _const_nary_tree_iterator() : m_cur(0) {}
00156           _const_nary_tree_iterator(_const_nary_tree_iterator const& it)
00157               : m_cur(it.m_cur) {}
00158           _const_nary_tree_iterator(_nary_tree_iterator<Node> const& it)
00159               : m_cur(it.m_cur) {}
00160           _const_nary_tree_iterator(_nary_tree_node_base* n)
00161               : m_cur(n) {}
00162           _const_nary_tree_iterator(_nary_tree_node_base const* n)
00163               : m_cur(const_cast<_nary_tree_node_base*>(n)) {}
00164           _const_nary_tree_iterator&
00165           operator=(_const_nary_tree_iterator const& it)
00166           { m_cur = it.m_cur; return *this; }
00167 
00168           bool operator==(_const_nary_tree_iterator const& it) const
00169           { return m_cur == it.m_cur; }
00170           bool operator!=(_const_nary_tree_iterator const& it) const
00171           { return m_cur != it.m_cur; }
00172 
00173           _const_nary_tree_iterator& operator++()
00174           { m_cur = m_cur->next(); return *this; }
00175           _const_nary_tree_iterator operator++(int)
00176           { _const_nary_tree_iterator tmp = *this; ++*this; return tmp; }
00177           _const_nary_tree_iterator& operator--()
00178           { m_cur = m_cur->prev(); return *this; }
00179           _const_nary_tree_iterator operator--(int)
00180           { _const_nary_tree_iterator tmp = *this; --*this; return tmp; }
00181 
00182           self begin() { return static_cast<Node*>(m_cur)->begin(); }
00183           self end() { return static_cast<Node*>(m_cur)->end(); }
00184           bool empty() { return begin() == end(); }
00185 
00186           self parent()
00187           {
00188               if (!m_cur->m_parent)
00189                   throw std::logic_error("_const_nary_tree_iterator::parent(): "
00190                                          "Root node has no parent.");
00191               return static_cast<Node*>(m_cur)->parent();
00192           }
00193 
00194           reference operator*() { return static_cast<Node*>(m_cur)->value; }
00195           pointer operator->() { return &static_cast<Node*>(m_cur)->value; }
00196 
00197         private:
00198           _nary_tree_node_base* m_cur;
00199 
00200           friend class _nary_tree_node<value_type>;
00201           template<typename U, typename Allocator> friend class nary_tree;
00202       };
00203 
00204     template<typename T>
00205       struct _nary_tree_node
00206           : protected _nary_tree_node_base
00207       {
00208           typedef _nary_tree_node self;
00209           typedef _nary_tree_node_base node_base;
00210           typedef _nary_tree_iterator<self> iterator;
00211           typedef _const_nary_tree_iterator<self> const_iterator;
00212           typedef T value_type;
00213           typedef T& reference;
00214           typedef T const& const_reference;
00215           typedef T* pointer;
00216           typedef ptrdiff_t difference_type;
00217           typedef size_t size_type;
00218 
00219           _nary_tree_node() { m_inf_child.m_parent = this; }
00220           _nary_tree_node(const_reference x)
00221               : value(x) { m_inf_child.m_parent = this;}
00222           ~_nary_tree_node() { unlink(); }
00223 
00224           self* parent() { return static_cast<self*>(m_parent); }
00225           self const* parent() const {
00226               return static_cast<self const*>(m_parent);
00227           }
00228 
00229           iterator begin() { return inf_child()->next(); }
00230           iterator end()   { return inf_child(); }
00231           const_iterator begin() const { return inf_child()->next(); }
00232           const_iterator end()   const { return inf_child(); }
00233 
00234           iterator insert(iterator it_pos, _nary_tree_node* v);
00235           _nary_tree_node* erase(iterator it_pos);
00236 
00237         private:
00238           node_base* inf_child() { return &m_inf_child; }
00239           node_base const* inf_child() const { return &m_inf_child; }
00240 
00241           _nary_tree_node_base m_inf_child;
00242           value_type value;
00243 
00244           friend class iterator;
00245           friend class const_iterator;
00246           template<typename U, typename Allocator> friend class nary_tree;
00247       };
00248   } // bits
00249   ///\endif
00250 
00251   /** \class nary_tree nary_tree.h more/gen/nary_tree.h
00252    **
00253    ** A tree with variable number of branches on each node.  See also
00254    ** <tt>ntree</tt>. */
00255   template< typename T, typename Allocator = gen::allocator<T> >
00256     struct nary_tree
00257     {
00258         typedef Allocator allocator_type;
00259         typedef bits::_nary_tree_node<T> node_type;
00260       private:
00261         typedef typename allocator_type::rebind<node_type>::other
00262                 real_allocator_type;
00263       public:
00264         typedef typename node_type::iterator iterator;
00265         typedef typename node_type::const_iterator const_iterator;
00266         typedef typename node_type::pointer pointer;
00267         typedef typename node_type::reference reference;
00268         typedef typename node_type::const_reference const_reference;
00269         typedef typename node_type::size_type size_type;
00270         typedef typename node_type::difference_type difference_type;
00271 
00272         nary_tree()
00273             : m_root(m_alloc.allocate(1))
00274         {
00275             m_alloc.construct(m_root);
00276         }
00277 
00278         nary_tree(nary_tree const& tr)
00279             : m_root(m_alloc.allocate(1))
00280         {
00281             m_alloc.construct(m_root);
00282             copy_node(tr.m_root, m_root);
00283         }
00284 
00285         ~nary_tree()
00286         {
00287             clear();
00288             m_alloc.destroy(m_root);
00289             m_alloc.deallocate(m_root, 1);
00290         }
00291 
00292         nary_tree&
00293         operator=(nary_tree const& tr)
00294         {
00295             clear();
00296             copy_node(tr.m_root, m_root);
00297             return *this;
00298         }
00299 
00300         struct swapper
00301         {
00302             swapper()
00303                 : m_root(m_alloc.allocate(1))
00304             {
00305                 m_alloc.construct(m_root);
00306             }
00307             swapper(nary_tree& t)
00308                 : m_root(m_alloc.allocate(1))
00309             {
00310                 m_alloc.construct(m_root);
00311                 std::swap(m_root, t.m_root);
00312             }
00313             swapper(swapper& sw)
00314                 : m_root(m_alloc.allocate(1))
00315             {
00316                 m_alloc.construct(m_root);
00317                 std::swap(m_root, sw.m_root);
00318             }
00319             swapper& operator=(nary_tree& t)
00320             {
00321                 std::swap(m_root, t.m_root);
00322                 return *this;
00323             }
00324             swapper& operator=(swapper& sw)
00325             {
00326                 std::swap(m_root, sw.m_root);
00327                 return *this;
00328             }
00329             ~swapper()
00330             {
00331                 nary_tree t(*this);
00332                 m_alloc.destroy(m_root);
00333                 m_alloc.deallocate(m_root, 1);
00334             }
00335 
00336           private:
00337             swapper(swapper const&) {}
00338             swapper& operator=(swapper const&) {}
00339 
00340             node_type* m_root;
00341             real_allocator_type m_alloc;
00342             friend class nary_tree;
00343         };
00344 
00345         nary_tree(swapper& sw)
00346             : m_root(m_alloc.allocate(1))
00347         {
00348             m_alloc.construct(m_root);
00349             std::swap(m_root, sw.m_root);
00350         }
00351 
00352         nary_tree& operator=(swapper& sw)
00353         {
00354             std::swap(m_root, sw.m_root);
00355             return *this;
00356         }
00357 
00358         void set_root(const_reference x)
00359         {
00360             m_root->value = x;
00361         }
00362 
00363         iterator        root() { return iterator(m_root); }
00364         const_iterator  root() const { return const_iterator(m_root); }
00365 
00366         iterator insert(iterator it_pos, const_reference v)
00367         {
00368             node_type* n_new = m_alloc.allocate(1);
00369             m_alloc.construct(n_new);
00370             n_new->value = v;
00371             return static_cast<node_type*>(it_pos.m_cur->m_parent)
00372                 ->insert(it_pos, n_new);
00373         }
00374 
00375         iterator erase(iterator it_pos)
00376         {
00377             node_type* n_old = static_cast<node_type*>(it_pos.m_cur);
00378             erase(n_old->begin(), n_old->end());
00379             node_type* n_next = static_cast<node_type*>(n_old->m_next);
00380             m_alloc.destroy(n_old);
00381             m_alloc.deallocate(n_old, 1);
00382             return iterator(n_next);
00383         }
00384 
00385         void erase(iterator first, iterator last)
00386         {
00387             while (first != last)
00388                 first = erase(first);
00389         }
00390 
00391         void clear() { erase(m_root->begin(), m_root->end()); }
00392 
00393         void swap(nary_tree& x)
00394         {
00395             std::swap(m_root, x.m_root);
00396         }
00397 
00398       private:
00399         void copy_node(node_type const* src, node_type* dst);
00400 
00401         real_allocator_type m_alloc;
00402         node_type* m_root;
00403     };
00404 
00405   template<typename TreeIterator0, typename TreeIterator1>
00406     bool
00407     subtree_counted_equal(TreeIterator0 it0, TreeIterator0 it0end,
00408                           TreeIterator1 it1, TreeIterator1 it1end)
00409     {
00410         for (;;) {
00411             if (it0 == it0end)
00412                 return it1 == it1end;
00413             if (it1 == it1end)
00414                 return false;
00415             if (*it0 != *it1)
00416                 return false;
00417             if (!subtree_counted_equal(it0.begin(), it0.end(),
00418                                        it1.begin(), it1.end()))
00419                 return false;
00420             ++it0;
00421             ++it1;
00422         }
00423     }
00424 
00425   template<typename T0, typename T1>
00426     bool
00427     operator==(nary_tree<T0> const& t0, nary_tree<T1> const& t1)
00428     {
00429         return *t0.root() == *t1.root()
00430             && subtree_counted_equal(t0.root().begin(), t0.root().end(),
00431                                      t1.root().begin(), t1.root().end());
00432     }
00433 
00434   template<typename T, typename Allocator>
00435     inline void
00436     nary_tree<T, Allocator>::copy_node(node_type const* src, node_type* dst)
00437     {
00438         dst->value = src->value;
00439         for (typename node_type::const_iterator it = src->begin();
00440              it != src->end(); ++it) {
00441             node_type* nd = m_alloc.allocate(1);
00442             m_alloc.construct(nd);
00443             copy_node(static_cast<node_type const*>(it.m_cur), nd);
00444             dst->insert(dst->end(), nd);
00445         }
00446     }
00447 
00448   template<typename T, typename Allocator>
00449     inline void
00450     swap(nary_tree<T, Allocator>& x, nary_tree<T, Allocator>& y)
00451     {
00452         x.swap(y);
00453     }
00454 
00455   template<typename TreeIterator>
00456     void
00457     subtree_dump(TreeIterator it, std::ostream& os,
00458                  int level = 0, unsigned int cont = 0)
00459     {
00460         if (level) {
00461             for (int i = 0; i < level; ++i)
00462                 os << (cont & (1<<i)? "|  " : "   ");
00463             os << "|\n";
00464         }
00465         for (int i = 0; i < level; ++i)
00466             os << (cont & (1<<i)? "|  " : "   ");
00467         os << (level? '+' : '-')
00468            << (it.empty()? "----" : "--+-") << *it << '\n';
00469         cont |= 2<<level;
00470         for (TreeIterator it_sub = it.begin(); it_sub != it.end(); ++it_sub) {
00471             if (it_sub == --it.end())
00472                 cont &= ~(2<<level);
00473             subtree_dump(it_sub, os, level+1, cont);
00474         }
00475     }
00476 
00477   ///\if bits
00478   namespace bits {
00479     template<typename T>
00480       typename _nary_tree_node<T>::iterator
00481       _nary_tree_node<T>::insert(iterator it_pos, _nary_tree_node* n_new)
00482       {
00483           node_base* n_pos = it_pos.m_cur;
00484           n_new->m_next = n_pos;
00485           n_new->m_prev = n_pos->m_prev;
00486           n_pos->m_prev = n_new;
00487           n_new->m_prev->m_next = n_new;
00488           n_new->m_parent = this;
00489           return iterator(n_new);
00490       }
00491 
00492     template<typename T>
00493       _nary_tree_node<T>*
00494       _nary_tree_node<T>::erase(iterator it_pos)
00495       {
00496           self* n_pos = static_cast<self*>(it_pos.m_cur);
00497           node_base* n_next = n_pos->m_next;
00498           n_pos->m_prev->m_next = n_next;
00499           n_next->m_prev = n_pos->m_prev;
00500           return n_pos;
00501       }
00502   } // bits
00503   ///\endif
00504 
00505 }} // more::gen
00506 
00507 #endif

Generated on Sat Sep 7 19:11:13 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.