LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiTree.h

00001 /*
00002  * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /*----------------------------------------------------------------
00025  * project ....: LTI Digital Image/Signal Processing Library
00026  * file .......: ltiTree.h
00027  * authors ....: Pablo Alvarado
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 23.11.00
00030  * revisions ..: $Id: ltiTree.h,v 1.15 2006/02/08 12:48:43 ltilib Exp $
00031  */
00032 
00033 #ifndef _LTI_TREE_H_
00034 #define _LTI_TREE_H_
00035 
00036 #include "ltiObject.h"
00037 #include "ltiMathObject.h"
00038 #include "ltiException.h"
00039 #include "ltiMath.h"
00040 #include <list>
00041 #include <vector>
00042 
00043 namespace lti {
00044   /**
00045    * Tree container class.
00046    *
00047    * The lti::tree class allows the representation of rooted ordered trees.
00048    *
00049    * The tree class is a container class implemented as template.
00050    * The template type T is the type of a data element contained in each
00051    * node of the tree, independently if it is a leaf or not.  The only
00052    * requirement for the type T is that is must not depend on dynamic
00053    * allocation of internal data.
00054    *
00055    * All types defined in ltiTypes.h use static members and can be
00056    * contained by the lti::tree class.
00057    *
00058    * The tree is always created empty.   You can however specify in the
00059    * constructor a default degree, i.e. the maximal number of childs
00060    * to be expected per node.
00061    * 
00062    * The first element will be inserted with pushRoot().
00063    *
00064    * @ingroup gAggregate
00065    */
00066   template<class T>
00067   class tree : public mathObject {
00068 
00069   public:
00070     /**
00071      * Type of the data in the nodes of the tree
00072      */
00073     typedef T value_type;
00074 
00075     /**
00076      * Return type of the size() member
00077      */
00078     typedef int size_type;
00079 
00080     class node;
00081     class iterator;
00082     class const_iterator;
00083 
00084   protected:
00085     /**
00086      * The nodeManager takes care of the memory administration.  It is
00087      * required to ensure that the iterators do not access invalid memory
00088      */
00089     class nodeManager {
00090     public:
00091 
00092       /**
00093        * Constructor
00094        * @param n the degree of each new node created
00095        */
00096       nodeManager(const int& n) : theSize(0),theDegree(n) {};
00097 
00098       /**
00099        * Creates a new node and returns the index of that node in theNodes
00100        * @param n initial number of children (degree) for this node
00101        * @param theNewParent the parent node of this node
00102        * @param newData the data to be hold on this node
00103        * @return the index of this node in theNodes
00104        */
00105       node* createNode(const int& n,
00106                        node& theNewParent,
00107                        const T& newData=T()) {
00108         int idx;
00109         // check if there are free nodes in the index list
00110         if (freedNodes.empty()) {
00111           // no more nodes free!
00112           // add a new node in theNodes
00113 
00114           idx = static_cast<int>(theNodes.size());
00115           node* newNode = new node(n,theNewParent,*this,newData,idx);
00116           theNodes.push_back(newNode);
00117 
00118         } else {
00119           // take the first free index
00120           idx = freedNodes.front();
00121           freedNodes.pop_front();
00122 
00123           node* newNode = new node(n,theNewParent,*this,newData,idx);
00124           theNodes[idx] = newNode;
00125         }
00126 
00127         theSize++;
00128 
00129         return theNodes[idx];
00130       };
00131 
00132       /**
00133        * Creates a new node and returns the index of that node in theNodes
00134        * @param n initial number of children (degree) for this node
00135        * @param theNewParent pointer to the parent node of this node
00136        * @param newData the data to be hold on this node
00137        * @return the index of this node in theNodes
00138        */
00139       node* createNode(const int& n,
00140                        node* theNewParent,
00141                        const T& newData=T()) {
00142         int idx;
00143         // check if there are free nodes in the index list
00144         if (freedNodes.empty()) {
00145           // no more nodes free!
00146           // add a new node in theNodes
00147 
00148           idx = static_cast<int>(theNodes.size());
00149           node* newNode = new node(n,theNewParent,*this,newData,idx);
00150           theNodes.push_back(newNode);
00151 
00152         } else {
00153           // take the first free index
00154           idx = freedNodes.front();
00155           freedNodes.pop_front();
00156 
00157           node* newNode = new node(n,theNewParent,*this,newData,idx);
00158           theNodes[idx] = newNode;
00159         }
00160 
00161         theSize++;
00162 
00163         return theNodes[idx];
00164       };
00165 
00166       /**
00167        * Creates a new node with the standard degree (specified in
00168        * construction of the node manager) and returns the index of that
00169        * node in theNodes
00170        * @param theNewParent the parent node of this node
00171        * @param newData the data to be hold on this node
00172        * @return the index of this node in theNodes
00173        */
00174       node* createNode(node& theNewParent,
00175                        const T& newData=T()) {
00176         return createNode(theDegree,theNewParent,newData);
00177       };
00178 
00179 
00180       /**
00181        * Free the given node and all its sucessors
00182        */
00183       void freeNode(node& theNode) {
00184         if (isNull(&theNode)) {
00185           return;
00186         }
00187 
00188         // first, free all children
00189         int i,ldegree;
00190         ldegree = theNode.degree();
00191         for (i=0;i<ldegree;++i) {
00192           if (theNode.isChildValid(i)) {
00193             freeNode(theNode.child(i));
00194           }
00195         }
00196 
00197         int idx;
00198 
00199         idx = theNode.index();
00200 
00201         delete theNodes[idx];
00202         theNodes[idx]=0;
00203 
00204         freedNodes.push_back(idx);
00205 
00206         theSize--;
00207       };
00208 
00209       /**
00210        * Get pointer to the node at the given index
00211        */
00212       node* getNode(const int& idx) {
00213         if (idx<static_cast<int>(theNodes.size())) {
00214           return theNodes[idx];
00215         } else {
00216           return 0;
00217         }
00218       };
00219 
00220       /**
00221        * Get pointer to the node at the given index
00222        */
00223       const node* getNode(const int& idx) const  {
00224         if (idx<static_cast<int>(theNodes.size())) {
00225           return theNodes[idx];
00226         } else {
00227           return 0;
00228         }
00229       };
00230 
00231       /**
00232        * Get index of the given node
00233        */
00234       int getIndexOfNode(const node& aNode) const {
00235         return aNode.index();
00236       };
00237 
00238       /**
00239        * Returns the number of valid nodes until now
00240        */
00241       const int& size() const {return theSize;}
00242 
00243     protected:
00244       /**
00245        * The container vector of all nodes of the tree
00246        */
00247       std::vector<node*> theNodes;
00248 
00249       /**
00250        * Freed nodes.
00251        *
00252        * This list contains the indices of freed nodes, which can be used
00253        * by the next createNode
00254        */
00255       std::list<int> freedNodes;
00256 
00257       /**
00258        * Number of valid nodes
00259        */
00260       int theSize;
00261 
00262       /**
00263        * Tree degree
00264        */
00265       int theDegree;
00266     };
00267 
00268   public:
00269 
00270     /**
00271      * The elements of the tree are instances of the "node" class
00272      */
00273     class node : public ioObject {
00274       /*
00275        * the node manager requires access to some protected member of
00276        * the node class, which should not be seen by the user
00277        */
00278       friend class nodeManager;
00279       friend class tree<T>;
00280 
00281     protected:
00282       /**
00283        * The children of this node as pointers to nodes
00284        */
00285       std::vector<node*> children;
00286 
00287       /**
00288        * A pointer to the parent node or 0 if this is a root node
00289        */
00290       node* theParent;
00291 
00292       /**
00293        * A pointer to the owner nodeManager
00294        */
00295       nodeManager* theOwner;
00296 
00297       /**
00298        * The data hold by this node
00299        */
00300       T theData;
00301 
00302       /**
00303        * The index of this node on the tree nodes-list
00304        */
00305       int myIndex;
00306 
00307       /**
00308        * Return a const reference to the index of this node in the nodeManager
00309        */
00310       inline const int& index() const {return myIndex;};
00311 
00312       /**
00313        * The level of this node, defined as the lenght of the path
00314        * from this node to the root.  i.e. if this node is root, its level is 0
00315        */
00316       int theLevel;
00317 
00318 
00319     public:
00320       // due to a bug in MSVC++ the class implementation must be here!
00321 
00322       /**
00323        * Copy constructor
00324        */
00325       node(const node& other) {
00326         copy(other);
00327       }
00328 
00329       /**
00330        * Destructor
00331        */
00332       virtual ~node() {
00333       }
00334 
00335       /**
00336        * Return true if the n-th child of this node has valid data or
00337        * false otherwise
00338        */
00339       bool isChildValid(const int& n) const {
00340         return ( n<degree() && children[n]!=0 );
00341       }
00342 
00343       /**
00344        * Access the n-th child of the node.
00345        *
00346        * If n is greater or equal than the degree, an assertion will be thrown
00347        * If the n-th child has not been initialized yet, an invalid reference
00348        * will be returned!.  To check if a child is valid use isChildValid().
00349        */
00350       const node& child(const int& n) const {
00351         assert(n<degree());
00352         return *children[n];
00353       }
00354 
00355       /**
00356        * Access a child.
00357        *
00358        * If n is greater or equal than the degree, an assertion will be thrown
00359        * If the n-th child has not been initialized yet, an invalid reference
00360        * will be returned!.  To check if a child is valid use isChildValid().
00361        */
00362       node& child(const int& n) {
00363         assert(n<degree());
00364 
00365         return *children[n];
00366       }
00367 
00368       /**
00369        * Change the degree of this node.
00370        *
00371        * @param n new degree
00372        * @param clear (default false) if true, this node will be
00373        *              (re)initialized as a leaf (i.e. all children NULL!)
00374        */
00375       void setDegree(const int& n,bool clear = false) {
00376         int i;
00377         int ldegree = degree();
00378 
00379         if (clear) {
00380           for (i=0;i<ldegree;++i) {
00381             // this will call recursively the destruction of the whole branch!
00382             theOwner->freeNode(*children[i]);
00383             children[i]=0;
00384           }
00385           children.resize(0,0);
00386         } else {
00387           if (n<ldegree) {
00388             for (i=n;i<ldegree;++i) {
00389               // this will call recursively the destruction of the
00390               // whole branch!
00391               theOwner->freeNode(*children[i]);
00392               children[i]=0;
00393             }
00394           }
00395         }
00396 
00397         children.resize(n,0); // initialize new elements with invalid
00398       };
00399 
00400       /**
00401        * Append a new child node with the given data.
00402        *
00403        * The new node will be inserted "at the end" of the node as a new child,
00404        * increasing the actual node degree.
00405        * The degree of the new child will be the specified degree for the tree
00406        * @return a reference to the new child
00407        */
00408       node& appendChild(const T& newChildData) {
00409 //         int ldegree;
00410 
00411 //         ldegree = degree();
00412 
00413         children.push_back(theOwner->createNode(*this,newChildData));
00414 
00415         return *children[children.size()-1];
00416       };
00417 
00418 
00419       /**
00420        * Insert a new child node with the given data.
00421        *
00422        * The new node will be inserted at the first uninitialized child.  If
00423        * all children are already initialized, the degree of this node will
00424        * be incremented and the new child will contain the given data.
00425        * The degree of the new child will be the specified degree for the tree
00426        * @return a reference to the new child
00427        */
00428       node& insertChild(const T& newChildData) {
00429         int i,ldegree;
00430 
00431         ldegree = degree();
00432         i=0;
00433         // search for the first not initialized child...
00434         while ((i<ldegree) && (children[i]!=0)) {
00435           ++i;
00436         }
00437 
00438         if (i>=ldegree) {
00439           // all children already initialized->create a new one
00440           setDegree(ldegree+1,false);
00441           children[ldegree] =
00442             theOwner->createNode(*this,newChildData);
00443           i = ldegree;
00444         } else {
00445           // i is the index to an uninizalized node
00446           children[i] = theOwner->createNode(*this,newChildData);
00447         }
00448 
00449         return *children[i];
00450       };
00451 
00452       /**
00453        * Insert a new child node with the given data at the given child index.
00454        *
00455        * If the node has already a child at the given position, the whole
00456        * branch will be inserted at the first child of the new node
00457        *
00458        * The degree of the new child will be the degree of this node
00459        */
00460       node& insertChild(const int& n,const T& newChildData) {
00461         assert(n < degree());
00462 
00463         node* newNode = theOwner->createNode(degree(),*this,newChildData);
00464 
00465         if (notNull(children[n])) {
00466           if (newNode->degree()<1) {
00467             newNode->setDegree(1);
00468           }
00469           newNode->setChild(0,*children[n]);
00470         }
00471 
00472         children[n]=newNode;
00473 
00474         return *children[n];
00475       }
00476 
00477       /**
00478        * Move a child branch to another position at this node.
00479        *
00480        * If the node has already a child at the given position, the whole
00481        * branch will be deleted.
00482        * @param m the old position
00483        * @param n the new position
00484        */
00485       node& moveChild(const int& m, const int& n) {
00486         assert(n < degree());
00487   
00488         if (notNull(children[n])) {
00489           theOwner->freeNode(*children[n]);
00490         }
00491 
00492         children[n] = children[m];
00493   children[m] = 0;
00494   
00495         return *children[n];
00496       }
00497 
00498       /**
00499        * Insert a new sibling node with the given data.
00500        *
00501        * The new node will be created at the first uninitialized sibling.  If
00502        * all siblings are already initialized, the degree of the parent will
00503        * be incremented and the new child will contain the given data.
00504        * The degree of the new child will be the new degree of the parent
00505        * An assertion will be thrown if this member is called for a root node
00506        * @return a reference to the new sibling
00507        */
00508       node& insertSibling(const T& newSiblingData) {
00509         assert(!isRoot());
00510 
00511         return parent().insertChild(newSiblingData);
00512       }
00513 
00514       /**
00515        * Delete the given child.
00516        *
00517        * @return a reference to this node
00518        */
00519       node& deleteChild(const int& n) {
00520         assert(n<degree());
00521         if (notNull(children[n])) {
00522           theOwner->freeNode(*children[n]);
00523           children[n]=0;
00524         }
00525         return *this;
00526       }
00527 
00528       /**
00529        * Check if this node is a root node (i.e. has no parent!)
00530        */
00531       bool isRoot() const {
00532         return (isNull(theParent));
00533       }
00534 
00535       /**
00536        * Access parent node.
00537        *
00538        * Please note that the returned reference can be invalid if this is the
00539        * root node.  To check this condition use isRoot()
00540        */
00541       node& parent() {
00542         return *theParent;
00543       };
00544 
00545       /**
00546        * Access parent node
00547        */
00548       const node& parent() const {
00549         return *theParent;
00550       };
00551 
00552       /**
00553        * Return the number of possible children of the node.
00554        * @see numberOfChildren()
00555        */
00556       int degree() const {
00557         return static_cast<int>(children.size());
00558       };
00559 
00560       /**
00561        * Calculate the number of valid children.
00562        *
00563        * This number is always less or equal degree().  The number of
00564        * valid children will be calculated and for that reason is
00565        * faster to ask for the degree() of the node.
00566        */
00567       int numberOfChildren() const {
00568         int i,ldegree,noc;
00569         ldegree = degree();
00570         noc = 0;
00571         for (i=0;i<ldegree;++i) {
00572           if (isChildValid(i)) {
00573             noc++;
00574           }
00575         }
00576         return noc;
00577       }
00578 
00579       /**
00580        * Return a reference to the node's data
00581        */
00582       T& getData() {
00583         return theData;
00584       }
00585 
00586       /**
00587        * Return a read-only reference to the node's data
00588        */
00589       const T& getData() const {
00590         return theData;
00591       }
00592 
00593       /**
00594        * Set the data of the node
00595        */
00596       void setData(const T& newData) {
00597         theData = newData;
00598       }
00599 
00600       /**
00601        * Copy the contents of the other node and of all its children.
00602        *
00603        * The parent will be kept. All the children will be also copied.
00604        * @param other the "root" node of the branch to be copied
00605        * @return a reference to this node
00606        * If you need to copy only the data of the node, you can use
00607        * for example <code>setData(other.getData());</code>
00608        */
00609       node& copy(const node& other) {
00610 
00611         setData(other.getData());
00612 
00613         setDegree(other.degree(),true); // clean all old children!
00614 
00615         // copy all the children
00616         int i,ldegree;
00617 
00618         ldegree = degree();
00619 
00620         for (i=0;i<ldegree;++i) {
00621           if (other.isChildValid(i)) {
00622             children[i] = theOwner->createNode(other.child(i).degree(),
00623                                               *this,
00624                                               T());
00625             children[i]->copy(other.child(i));
00626           }
00627         }
00628 
00629         theLevel = other.theLevel;
00630 
00631         return *this;
00632       }
00633 
00634       /**
00635        * Calculate the height of this node, defined as the length of
00636        * the longest path from this node to some leaf node.  If this
00637        * node is a leaf, the returned value is 0.
00638        * Please note that this function is highly recursive and could take
00639        * a while...
00640        */
00641       int height() const {
00642         int i,ldegree,result;
00643         ldegree = degree();
00644         result = 0;
00645         for (i=0;i<ldegree;++i) {
00646           if (isChildValid(i)) {
00647             result = max(result,1+child(i).height());
00648           }
00649         }
00650 
00651         return result;
00652       };
00653 
00654       /**
00655        * Calculates the size (total number of valid nodes) of the
00656        * subtree beginning with this node.  If this node is a leaf,
00657        * the returned value is 1 Please note that this function is
00658        * highly recursive and could take a while...
00659        */
00660       int subtreeSize() const {
00661         int i,ldegree,result;
00662         ldegree = degree();
00663         result = 1;
00664         for (i=0;i<ldegree;++i) {
00665           if (isChildValid(i)) {
00666             result += child(i).subtreeSize();
00667           }
00668         }
00669 
00670         return result;
00671       };
00672 
00673       /**
00674        * Returns the level of this node, defined as the lenght of the path
00675        * from this node to the root.  i.e. if this node is root, its level is 0
00676        */
00677       const int& level() const {
00678         return theLevel;
00679       };
00680 
00681       /**
00682        * Calulates the position of this node for the parent.  If this
00683        * node is root, the returned value will be negative. 
00684        *
00685        * For example, let aNode be a non-root node, the following
00686        * expression will return always true:
00687        * aNode.isSameNode(aNode.parent().child(aNode.position()))
00688        */
00689       int position() const {
00690         if (isRoot()) {
00691           return -1;
00692         }
00693 
00694         int i,ldegree,idx;
00695 
00696         ldegree = parent().degree();
00697         idx = -1;
00698         for (i=0;(idx<0) && (i<ldegree);++i) {
00699           if (isSameNode(parent().child(i))) {
00700             idx = i;
00701           }
00702         }
00703 
00704         return idx;
00705       }
00706 
00707       /**
00708        * Return true if both nodes contains equal data AND if all its
00709        * children are equal.  If you need to compare only the data of this
00710        * node, you can do it explicitly with getData()==other.getData().
00711        */
00712       bool equals(const node& other) {
00713         bool result;
00714 
00715         result = (getData() == other.getData) &&
00716           (degree() == other.degree()) &&
00717           (size() == other.size()) &&
00718           (height() == other.height());
00719 
00720         int i,ldegree;
00721         ldegree = degree();
00722         i=0;
00723         while ((i<ldegree) && (result)) {
00724           if (isChildValid(i) && other.isChildValid(i)) {
00725             result = result && (child(i).equals(other.child(i)));
00726           } else if (isChildValid(i) || other.isChildValid(i)) {
00727             result = false;
00728           }
00729           i++;
00730         }
00731         return result;
00732       }
00733 
00734       /**
00735        * Return true if both nodes are exactly the same node
00736        */
00737       inline bool isSameNode(const node& other) const {
00738         return (this == &other);
00739       }
00740 
00741       /**
00742        * Return true if the this node is the parent of the other node
00743        */
00744       inline bool isParentOf(const node& other) const {
00745         if (!other.isRoot()) {
00746           return (isSameNode(other.parent()));
00747         }
00748         return false;
00749       }
00750 
00751       /**
00752        * Return true if the other node is a sibling of this node.
00753        * A node is NOT a sibling of itself.
00754        */
00755       inline bool isSiblingOf(const node& other) const {
00756         if (!isRoot() && !other.isRoot() && !isSameNode(other)) {
00757           return (parent().isSameNode(other.parent()));
00758         }
00759         return false;
00760       }
00761 
00762       /**
00763        * Equals topology returns true if this and the other tree
00764        * have exactly the same topology (the same valid children and
00765        * all children have the same topology
00766        */
00767       bool equalsTopology(const node& other) {
00768         bool result;
00769 
00770         result = (degree() == other.degree());
00771 
00772         int i,ldegree;
00773         ldegree = degree();
00774         i=0;
00775 
00776         while ((i<ldegree) && (result)) {
00777           if (isChildValid(i) && other.isChildValid(i)) {
00778             result = result && (child(i).equalsTopology(other.child(i)));
00779           } else if (isChildValid(i) || other.isChildValid(i)) {
00780             result = false;
00781           }
00782           i++;
00783         }
00784 
00785         return result;
00786       }
00787 
00788       // -----------------------------
00789       /**
00790        * @name Storable interface
00791        */
00792       //@{
00793 
00794 #     ifndef _LTI_MSC_6
00795       /**
00796        * Write the parameters in the given ioHandler
00797        * @param handler the ioHandler to be used
00798        * @param complete if true (the default) the enclosing begin/end will
00799        *        be also written, otherwise only the data block will be written.
00800        * @return true if write was successful
00801        */
00802       virtual bool write(ioHandler& handler,const bool complete=true) const
00803 #     else
00804       /**
00805        * This function is required by MSVC only, as a workaround for a
00806        * very awful bug, which exists since MSVC V.4.0, and still by
00807        * V.6.0 with all bugfixes (so called "service packs") remains
00808        * there...  This method is also public due to another bug, so please
00809        * NEVER EVER call this method directly: use write() instead
00810        */
00811       bool writeMS(ioHandler& handler,const bool complete=true) const
00812 #     endif
00813       {
00814         bool b = true;
00815         if (complete) {
00816           b = handler.writeBegin();
00817         }
00818 
00819         // write the data contained in this node first
00820         b = b && lti::write(handler,theData);
00821         b = b && handler.writeDataSeparator();
00822         // now write the number of children of this node
00823         const int ldegree = degree();
00824         b = b && handler.write(degree());
00825         b = b && handler.writeDataSeparator();
00826 
00827         // now write the children recursivelly
00828         b = b && handler.writeBegin();
00829         
00830         int i;
00831         for (i=0;b && (i<ldegree);++i) {
00832           if (isChildValid(i)) {
00833             child(i).write(handler);
00834           } else {
00835             // empty node
00836             handler.writeBegin();
00837             handler.writeEnd();
00838           }
00839         }        
00840 
00841         b = b && handler.writeEnd(); // end of children.
00842         b = b && handler.writeEOL();
00843 
00844         if (complete) {
00845           b = b && handler.writeEnd();
00846         }
00847 
00848         return b;
00849       }
00850 
00851 #     ifdef _LTI_MSC_6
00852       /**
00853        * Write the parameters in the given ioHandler
00854        * @param handler the ioHandler to be used
00855        * @param complete if true (the default) the enclosing begin/end will
00856        *        be also written, otherwise only the data block will be written.
00857        * @return true if write was successful
00858        */
00859       bool write(ioHandler& handler,
00860                  const bool complete=true) const {
00861         // ...we need this workaround to cope with another really
00862         // awful MSVC bug.
00863         return writeMS(handler,complete);
00864       }
00865 #     endif
00866 
00867 
00868 #     ifndef _LTI_MSC_6
00869       /**
00870        * Read the parameters from the given ioHandler
00871        * @param handler the ioHandler to be used
00872        * @param complete if true (the default) the enclosing begin/end will
00873        *        be also written, otherwise only the data block will be written.
00874        * @return true if write was successful
00875        */
00876       virtual bool read(ioHandler& handler,const bool complete=true)
00877 #     else
00878       /**
00879        * This function is required by MSVC only, as a workaround for a
00880        * very awful bug, which exists since MSVC V.4.0, and still by
00881        * V.6.0 with all bugfixes (so called "service packs") remains
00882        * there...  This method is also public due to another bug, so please
00883        * NEVER EVER call this method directly: use read() instead
00884        */
00885       bool readMS(ioHandler& handler,const bool complete=true)
00886 #     endif
00887       {
00888         bool b = true;
00889         if (complete) {
00890           b = handler.readBegin();
00891         }
00892 
00893         // read the data of the node
00894         b = b && lti::read(handler,theData);
00895         b = b && handler.readDataSeparator();
00896 
00897         // now read and set the number of children of this node
00898         int ldegree;
00899         b = b && handler.read(ldegree);
00900         setDegree(ldegree,true); // clear all subtrees!
00901         
00902         b = b && handler.readDataSeparator();
00903 
00904         // now read the rest of the nodes recursivelly
00905         b = b && handler.readBegin();
00906 
00907         int i;
00908         for (i=0;b && (i<ldegree);++i) {
00909           b = b && handler.readBegin();
00910           if (!handler.tryEnd()) {
00911             // a node was found, let's read it recursivelly
00912             insertChild(i,T());
00913             b = b && child(i).read(handler,false);
00914             b = b && handler.readEnd();
00915           }
00916         }
00917         
00918         b = b && handler.readEnd();
00919         
00920         if (complete) {
00921           b = b && handler.readEnd();
00922         }
00923         
00924         return b;
00925       }
00926 
00927 #     ifdef _LTI_MSC_6
00928       /**
00929        * Read the parameters from the given ioHandler
00930        * @param handler the ioHandler to be used
00931        * @param complete if true (the default) the enclosing begin/end will
00932        *        be also written, otherwise only the data block will be written.
00933        * @return true if write was successful
00934        */
00935       bool read(ioHandler& handler,const bool complete=true) {
00936         // ...we need this workaround to cope with another really awful MSVC
00937         // bug.
00938         return readMS(handler,complete);
00939       }
00940 #     endif
00941       //@}
00942 
00943 
00944     protected:
00945 
00946       /**
00947        * Protected constructor: only the nodeManager is allowed to generate new
00948        * nodes!
00949        *
00950        * @param n initial number of children (degree) for this node
00951        * @param theNewParent the parent node of this node
00952        * @param owner the tree which owns this node
00953        * @param newData the data to be hold on this node
00954        * @param index of this node on the tree
00955        */
00956       node(const int& n,
00957            node& theNewParent,
00958            nodeManager& owner,
00959            const T& newData,
00960            const int& index)
00961         : theParent(&theNewParent),theOwner(&owner),
00962           theData(newData),myIndex(index),theLevel(0) {
00963         children.resize(n,0);
00964         if (notNull(theParent)) {
00965           theLevel = theParent->level()+1;
00966         }
00967       };
00968 
00969       /**
00970        * Protected constructor: only the nodeManager is allowed to generate new
00971        * nodes!
00972        *
00973        * @param n initial number of children (degree) for this node
00974        * @param theNewParent the parent node of this node
00975        * @param owner the tree which owns this node
00976        * @param newData the data to be hold on this node
00977        * @param index of this node on the tree
00978        */
00979       node(const int& n,
00980            node* theNewParent,
00981            nodeManager& owner,
00982            const T& newData,
00983            const int& index)
00984         : theParent(theNewParent),theOwner(&owner),
00985           theData(newData),myIndex(index),theLevel(0) {
00986         children.resize(n,0);
00987         if (notNull(theParent)) {
00988           theLevel = theParent->level()+1;
00989         }
00990       };
00991 
00992       /**
00993        * Change the reference to the parent node.  Note that you
00994        * should make sure that the old parent forgets about this node!  */
00995       void setParent(node& newParent) {
00996         theParent = &newParent;
00997         updateLevels();
00998       }
00999 
01000       /**
01001        * Change the reference of a child node.
01002        * Be careful with the use of this
01003        * member function: after the use of the function there is no
01004        * way to get a reference to the old child, and this can produce
01005        * huge memory leaks!!!
01006        * the parent of the child will be changed to this node!
01007        */
01008       void setChild(const int& n,node& newChild) {
01009         assert(n<degree());
01010         children[n] = &newChild;
01011         newChild.theParent = this;
01012         updateLevels();
01013       }
01014 
01015       /**
01016        * Update parent size and height
01017        */
01018       void updateLevels() {
01019         if (notNull(theParent)) {
01020           theLevel = theParent->level()+1;
01021         }
01022 
01023         const int& ldegree = degree();
01024         const int tmpLevel = theLevel+1;
01025         int i;
01026 
01027         for (i=0;i<ldegree;++i) {
01028           if (isChildValid(i) && (child(i).level() != tmpLevel)) {
01029             child(i).updateLevels();
01030           }
01031         }
01032       }
01033 
01034     };
01035 
01036     /**
01037      * Iterator type (allows read and write operations)
01038      *
01039      * The use of the iterator classes is similar to the iterators of
01040      * the STL (Standard Template Library). See lti::tree::begin() for
01041      * an example
01042      *
01043      * CAUTION: Try to use the prefix incremental operator
01044      * (i.e. ++it) instead of the postfix operator (i.e. it++) to
01045      * allow efficient code!
01046      *
01047      * CAUTION: Do not delete sibling nodes of already iterated nodes:
01048      * the iterator keeps track of them, and if you delete them
01049      * invalid references to unexistent nodes could be returned by
01050      * late iterations.  It IS save to insert or delete children of
01051      * the nodes pointed by the iterator (but this could invalidate
01052      * other iterators on the same tree).  If you really really need
01053      * to do things like that, you should use your own node pointers
01054      * and iteration mechanisms :-(
01055      *
01056      * The iterators will traverse the tree in a prefix form (first the node
01057      * and then the children)
01058      */
01059     class iterator {
01060 
01061 #     ifdef _LTI_MSC_6
01062       friend class const_iterator;
01063 #     else
01064       friend class tree<T>::const_iterator;
01065 #     endif
01066 
01067       friend class tree<T>;
01068     protected:
01069       /**
01070        * Stack with all still-to-be-iterated-children
01071        */
01072       std::list<int> stack;
01073 
01074       /**
01075        * The pointed node
01076        */
01077       node* pointedNode;
01078 
01079       /**
01080        * The owner tree
01081        */
01082       nodeManager* theOwner;
01083 
01084       /**
01085        * Create an iterator initialized with the given pointer to a node
01086        */
01087       explicit iterator(node& theNode,nodeManager& owner)
01088         : pointedNode(&theNode),theOwner(&owner) {};
01089 
01090     public:
01091       /**
01092        * Default constructor
01093        */
01094       iterator() : pointedNode(0),theOwner(0) {};
01095 
01096 
01097       /**
01098        * Copy constructor
01099        */
01100       iterator(const iterator& other)
01101         : stack(other.stack),pointedNode(other.pointedNode),
01102           theOwner(other.theOwner) {};
01103 
01104       /**
01105        * Advance to next item (prefix increment operator)
01106        */
01107       inline iterator& operator++() {
01108         assert(notNull(pointedNode)); // the end() cannot be incremented!
01109 
01110         int i;
01111 
01112         const int size = pointedNode->degree() - 1;
01113 
01114         for (i=size;i>=0;i--) {
01115           if (pointedNode->isChildValid(i)) {
01116             stack.push_front(theOwner->getIndexOfNode(pointedNode->child(i)));
01117           }
01118         }
01119 
01120         if (stack.empty()) {
01121           pointedNode = 0;
01122         } else {
01123           do {
01124             const int idx = stack.front();
01125             stack.pop_front();
01126 
01127             pointedNode = theOwner->getNode(idx);
01128           } while (isNull(pointedNode) && (!stack.empty()));
01129 
01130         }
01131 
01132         return *this;
01133       };
01134 
01135       /**
01136        * Compare this iterator with the other one
01137        */
01138       inline bool operator==(const iterator& other) const {
01139         return (pointedNode == other.pointedNode);
01140       };
01141 
01142       /**
01143        * Compare this iterator with the other one
01144        */
01145       inline bool operator!=(const iterator& other) const {
01146         return (pointedNode != other.pointedNode);
01147       };
01148 
01149       /**
01150        * Get pointed data
01151        */
01152       inline node& operator*() {return *pointedNode;};
01153 
01154       /**
01155        * Copy member
01156        */
01157       inline iterator& operator=(const iterator& other) {
01158         pointedNode = other.pointedNode;
01159         stack = other.stack;
01160         theOwner = other.theOwner;
01161         return *this;
01162       };
01163     };
01164 
01165     /**
01166      * Const iterator type (allows read-only operations)
01167      *
01168      * The use of the iterator classes is similar to the iterators of
01169      * the STL (Standard Template Library). See lti::tree::begin() for
01170      * an example.
01171      *
01172      * CAUTION: Do not delete sibling nodes of already iterated nodes:
01173      * the iterator keeps track of them, and if you delete them
01174      * invalid references to unexistent nodes could be returned by
01175      * late iterations.  It IS save to insert or delete children of
01176      * the nodes pointed by the iterator (but this could invalidate
01177      * other iterators on the same tree).  If you really really need
01178      * to do things like that, you should use your own node pointers
01179      * and iteration mechanisms :-(
01180      */
01181     class const_iterator {
01182       friend class tree<T>;
01183     protected:
01184       /**
01185        * Stack with all still-to-be-iterated children
01186        */
01187       std::list<int> stack;
01188 
01189       /**
01190        * The pointed node
01191        */
01192       const node* pointedNode;
01193 
01194       /**
01195        * The owner tree
01196        */
01197       const nodeManager* theOwner;
01198 
01199       /**
01200        * Create an iterator initialized with the given pointer to a node
01201        */
01202       explicit const_iterator(const node& theNode,const nodeManager& owner)
01203         : pointedNode(&theNode),theOwner(&owner) {};
01204 
01205     public:
01206       /**
01207        * Default constructor
01208        */
01209       const_iterator() : pointedNode(0),theOwner(0) {};
01210 
01211       /**
01212        * Copy constructor
01213        */
01214       const_iterator(const const_iterator& other)
01215         : stack(other.stack),pointedNode(other.pointedNode),
01216           theOwner(other.theOwner) {};
01217 
01218       /**
01219        * Copy constructor
01220        */
01221       const_iterator(const iterator& other)
01222         : stack(other.stack),pointedNode(other.pointedNode),
01223           theOwner(other.theOwner) {
01224       };
01225 
01226       /**
01227        * Advance to next item (prefix increment operator)
01228        */
01229       inline const_iterator& operator++() {
01230         assert(notNull(pointedNode)); // the end() cannot be incremented!
01231 
01232         int i;
01233 
01234         const int size = pointedNode->degree() - 1;
01235 
01236         for (i=size;i>=0;i--) {
01237           if (pointedNode->isChildValid(i)) {
01238             stack.push_front(theOwner->getIndexOfNode(pointedNode->child(i)));
01239           }
01240         }
01241 
01242         if (stack.empty()) {
01243           pointedNode = 0;
01244         } else {
01245           do {
01246             const int idx = stack.front();
01247             stack.pop_front();
01248 
01249             pointedNode = theOwner->getNode(idx);
01250           } while (isNull(pointedNode) && (!stack.empty()));
01251         }
01252 
01253         return *this;
01254       };
01255 
01256       /**
01257        * Advance to next item (this postfix version is slower than the
01258        * prefix one
01259        */
01260       inline const_iterator operator++(int) { // postfix
01261         assert(notNull(pointedNode)); // the end() cannot be incremented!
01262         const_iterator tmp(*this);
01263 
01264         int i;
01265 
01266         const int size = pointedNode->degree() - 1;
01267 
01268         for (i=size;i>=0;i--) {
01269           if (pointedNode->isChildValid(i)) {
01270             stack.push_front(theOwner->getIndexOfNode(pointedNode->child(i)));
01271           }
01272         }
01273 
01274         if (stack.empty()) {
01275           pointedNode = 0;
01276         } else {
01277           do {
01278             const int idx = stack.front();
01279             stack.pop_front();
01280 
01281             pointedNode = theOwner->getNode(idx);
01282           } while (isNull(pointedNode) && (!stack.empty()));
01283         }
01284 
01285         return tmp;
01286       };
01287 
01288       /**
01289        * Compare this iterator with the other one
01290        */
01291       inline bool operator==(const const_iterator& other) const {
01292         return (pointedNode == other.pointedNode);
01293       };
01294 
01295       /**
01296        * Compare this iterator with the other one
01297        */
01298       inline bool operator!=(const const_iterator& other) const {
01299         return (pointedNode != other.pointedNode);
01300       };
01301 
01302       /**
01303        * Compare this iterator with the other one
01304        */
01305       inline bool operator==(const iterator& other) const {
01306         return (pointedNode == other.pointedNode);
01307       };
01308 
01309       /**
01310        * Compare this iterator with the other one
01311        */
01312       inline bool operator!=(const iterator& other) const {
01313         return (pointedNode != other.pointedNode);
01314       };
01315 
01316       /**
01317        * Get pointed data
01318        */
01319       inline const node& operator*() const {return *pointedNode;};
01320 
01321       /**
01322        * Copy member
01323        */
01324       inline const_iterator& operator=(const const_iterator& other) {
01325         pointedNode = other.pointedNode;
01326         stack = other.stack;
01327         theOwner = other.theOwner;
01328         return *this;
01329       };
01330 
01331       /**
01332        * Copy member
01333        */
01334       inline const_iterator& operator=(const iterator& other) {
01335         pointedNode = other.pointedNode;
01336         stack = other.stack;
01337         theOwner = other.theOwner;
01338         return *this;
01339       };
01340     };
01341 
01342     // ---------------------------------------------------------------
01343     //   TREE CLASS
01344     // ---------------------------------------------------------------
01345 
01346     /**
01347      * Default constructor
01348      *
01349      * If you do not provide any arguments, an empty tree of zero-degree
01350      * will be created.
01351      *
01352      * You can also provide the degree of the tree, which is the maximal number
01353      * of children a node can have, but even if you provide the degree, the
01354      * tree will be empty.  Use pushRoot to insert the first node in the tree.
01355      *
01356      * @param n the default number of children (degree) of the root node.
01357      */
01358     tree(const int& n=0);
01359 
01360     /**
01361      * Create this tree as a copy of another tree.
01362      *
01363      * @param other the tree to be copied.
01364      */
01365     tree(const tree<T>& other);
01366 
01367     /**
01368      * Destructor
01369      */
01370     virtual ~tree();
01371 
01372     /**
01373      * Returns the name of this class: "tree"
01374      */
01375     const char* getTypeName() const {return "tree";};
01376 
01377     /**
01378      * Returns the total number of nodes of the tree
01379      */
01380     inline size_type size() const;
01381 
01382     /**
01383      * Returns the height of the tree, defined as the length of the longest
01384      * path from the root to some leaf node
01385      */
01386     inline size_type height() const;
01387 
01388     /**
01389      * Returns const_iterator to a "first" node of the tree.  This node will
01390      * be allways the root
01391      * Note that you can not change the values of the tree
01392      * elements when you use a const_iterator. See also begin()
01393      */
01394     inline const_iterator begin() const;
01395 
01396     /**
01397      * Returns an iterator to the first element.
01398      *
01399      * The use of the interators is similar to the iterators of the
01400      * Standard Template Library (STL).
01401      * If you need to iterate on all elements of the tree, you can
01402      * use following code:
01403      *
01404      * \code
01405      * int tmp,accu;                   // a temporal variable
01406      * lti::tree<int> myTree();        // empty tree
01407      * // fill your tree here
01408      * lti::tree<int>::iterator it;    // an iterator
01409      *
01410      * for (it=myTree.begin();it!=myTree.end();++it) {
01411      *   tmp = (*it).getData();        // tmp has value of element pointed
01412      *                                 // by the iterator.
01413      *   accu += tmp;
01414      *   (*it).setData(accu);          // change the value in the tree.
01415      * }
01416      * \endcode
01417      *
01418      * Please note that if you define <code>it</code> as a const_iterator,
01419      * you can NOT make something like <code>*it=accu</code>.
01420      */
01421     inline iterator begin();
01422 
01423     /**
01424      * Returns last index as a const iterator.
01425      * For an example see begin()
01426      */
01427     inline const_iterator end() const;
01428 
01429     /**
01430      * Returns last index as an iterator
01431      * For an example see begin()
01432      */
01433     inline iterator end();
01434 
01435     /**
01436      * Return an iterator which points to the given node
01437      */
01438     inline iterator getIteratorTo(node& aNode);
01439 
01440     /**
01441      * Return a const_iterator which points to the given node
01442      */
01443     inline const_iterator getIteratorTo(const node& aNode) const;
01444 
01445     /**
01446      * Clears the tree (this tree will be empty!).
01447      * see fill(const T&) to initialize all tree nodes with some value
01448      */
01449     void clear();
01450 
01451     /**
01452      * Fills all tree elements with <code>iniValue</code>.
01453      *
01454      * @param iniValue the elements will be initialized with this
01455      * value.
01456      */
01457     void fill(const T& iniValue);
01458 
01459     /**
01460      * Return the root node of the tree.  Note that if the tree is empty
01461      * the reference is invalid.  Use empty() to check this
01462      */
01463     node& root();
01464 
01465     /**
01466      * Access element x of the tree in a read-only modus.  Note that if the
01467      * tree is empty, the reference is invalid.  Use empty() to check this.
01468      */
01469     const node& root() const;
01470 
01471     /**
01472      * Insert a node at the root position.
01473      *
01474      * pushRoot will insert the given data as the root of the tree,
01475      * and the old root will be inserted as its first child.  The root
01476      * will have the mininum between 1 and the degree specified in the
01477      * creation of the tree.
01478      *
01479      * If the tree was empty, it will have a new node with the given data.
01480      */
01481     void pushRoot(const T& newData);
01482 
01483     /**
01484      * Assigment operator.
01485      * copy the contents of <code>other</code> in this %object.
01486      * @param other the source tree to be copied.
01487      */
01488     tree<T>& copy(const tree<T>& other);
01489 
01490     /**
01491      * Create a clone of this tree
01492      * @return a pointer to a copy of this tree
01493      */
01494     virtual mathObject* clone() const;
01495 
01496     /**
01497      * Returns true if the tree is empty
01498      */
01499     bool empty() const;
01500 
01501     /**
01502      * Compare this tree with other
01503      * @param other the other tree to be compared with
01504      * @return true if both trees have the same elements and topology
01505      */
01506     bool equals(const tree<T>& other) const;
01507 
01508     /**
01509      * Compare this tree with other
01510      * @param other the other tree to be compared with
01511      * @return true if both trees have the same elements and topology
01512      */
01513     inline bool operator==(const tree<T>& other) const;
01514 
01515     /**
01516      * Assigment operator (alias for copy(other)).
01517      * @param other the tree to be copied
01518      * @return a reference to the actual tree
01519      */
01520     tree<T>& operator=(const tree<T>& other) {return copy(other);};
01521 
01522     /**
01523      * Write the functor in the given ioHandler. The default implementation
01524      * is to write just the parameters object.
01525      * @param handler the ioHandler to be used
01526      * @param complete if true (the default) the enclosing begin/end will
01527      *        be also written, otherwise only the data block will be written.
01528      * @return true if write was successful
01529      */
01530     virtual bool write(ioHandler& handler,
01531                        const bool complete=true) const;
01532 
01533     /**
01534      * Read the parameters from the given ioHandler. The default implementation
01535      * is to read just the parameters object.
01536      * @param handler the ioHandler to be used
01537      * @param complete if true (the default) the enclosing begin/end will
01538      *        be also written, otherwise only the data block will be written.
01539      * @return true if write was successful
01540      */
01541     virtual bool read(ioHandler& handler,const bool complete=true);
01542 
01543 
01544   protected:
01545     /**
01546      * The root of the tree
01547      */
01548     node* theRoot;
01549 
01550     /**
01551      * Degree for the root specified by the user in constructor
01552      */
01553     int rootDegree;
01554 
01555     /**
01556      * The node manager administrates the memory allocation and deallocation
01557      * for all nodes in the tree
01558      */
01559     nodeManager theNodeManager;
01560 
01561   };
01562 } // namespace lti
01563 
01564 #include "ltiTree_inline.h"
01565 #include "ltiTree_template.h"
01566 
01567 
01568 #endif

Generated on Sat Apr 10 15:26:19 2010 for LTI-Lib by Doxygen 1.6.1