// Node form for the family tree template class Tnode { public: Etype info; // The data Tnode *firstchild; // Points to first child (left) Tnode *sibling; // Points to a sibling (right) Tnode *parents; // Points to the parents (up) Tnode () : firstchild(NULL), sibling(NULL), parents(NULL) { } Tnode (const Etype & one) : info(one), firstchild(NULL), sibling(NULL), parents(NULL) { } }; // Template class for a family tree template class FTree { private: Tnode *root; // Pointer to root node void VisitAndDestroy(Tnode *); // To erase subtree FTree(const FTree &); // Make copy constructor public: // inaccessible class iterator; FTree(); // Create empty tree FTree (const Etype &); // Make single node tree ~FTree (); // Destroy tree bool empty () const; // Test for empty iterator begin() const; // Set iterator to root iterator end() const; // Make iterator invalid iterator insertL(iterator &, Etype &); // Add firstchild node iterator insertR(iterator &, Etype &); // Add sibling node void erase (iterator &); // Erase descendants class iterator // Nested iterator { private: Tnode * current; // Pointer to tree node iterator (Tnode * where) // Make iterator point to a node { current = where; } public: friend class FTree; // Set relationship to tree // Make iterator for client iterator(): current(NULL) { }; // Compare iterators for = bool operator == (iterator & rhs) { return current == rhs.current; } // Compare iterators for != bool operator != (iterator & rhs) { return current != rhs.current; } // Return reference to the Etype & operator* () // data in the node { if (current == NULL) throw logic_error ("Invalid dereference: *"); return current->info; } // Return pointer to the Etype * operator-> () // data in the node { if (current == NULL) throw logic_error ("Invalid dereference: ->"); return &(current->info); } // Return iterator referencing iterator DownFirst () // firstchild node { if (current == NULL) throw logic_error ("Invalid dereference: DownFirst"); return iterator(current->firstchild); } // Return iterator referencing iterator DownSibling () // next sibling node { if (current == NULL) throw logic_error ("Invalid dereference: DownSibling"); return iterator(current->sibling); } // Return iterator referencing iterator Up () // parents node { if (current == NULL) throw logic_error ("Invalid dereference: Up"); return iterator(current->parents); } }; }; // Recursive function to visit all nodes in subtree rooted // at start and delete each node template void FTree::VisitAndDestroy(Tnode *start) { if (start == NULL) return; else { VisitAndDestroy (start->firstchild); VisitAndDestroy (start->sibling); delete start; } } // Build empty tree template FTree::FTree (void) { root = NULL; } // Build tree with root only template FTree::FTree (const Etype & one) { root = new Tnode(one); } // Destroy whole tree template FTree::~FTree (void) { VisitAndDestroy (root); root = NULL; } // Test for empty tree template bool FTree::empty () const { return root == NULL; } // Return iterator pointing to root template FTree::iterator FTree::begin () const { return FTree::iterator(root); } // Return iterator referencing NULL template FTree::iterator FTree::end () const { return FTree::iterator(); } // Insert left child (firstchild) node template FTree::iterator FTree::insertL // Return iterator ref new node (FTree::iterator & where, // Iterator to parent Etype & one) // Data { Tnode * add; Tnode * was; was = where.current; add = new Tnode(one); // Create node with data if (was != NULL) // Fill in pointers { add->firstchild = was->firstchild; add->parents = was; was->firstchild = add; } else // Special case for making the root { add->firstchild = add->sibling = add->parents = NULL; root = add; } return FTree::iterator(add); // Return iterator to new node } // Insert right child (sibling) node template FTree::iterator FTree::insertR // Return iterator ref new node (FTree::iterator & where, // Iterator to parent node Etype & one) // Data to add { Tnode * add; Tnode * was; was = where.current; if (was == NULL) throw logic_error ("Can't attach to an invalid iterator position"); add = new Tnode(one); // Make new node with data add->sibling = was->sibling; // Fill in pointers add->parents = was->parents; was->sibling = add; return FTree::iterator(add); // Return iterator to new node } // Erase descendants from start template void FTree::erase (FTree::iterator & start) { Tnode * other; if (start.current == NULL) // Make sure start is valid throw logic_error ("Can't erase; tree is empty or iterator invalid"); other = start.current->parents; // Locate parents if (other != NULL) { if (start.current == other->firstchild) // If start if first child other->firstchild = start.current->sibling; // Disconnect it else { other = other->firstchild; while (other->sibling != start.current) // Find which sibling start is other = other->sibling; other->sibling = start.current->sibling;// Disconnect it } start.current->sibling = NULL; } VisitAndDestroy(start.current); // Clear subtree start = FTree::iterator(); // Invalidate iterator }