/* $Id: tree.hh,v 1.6 2006-07-20 04:41:16 benoitg Exp $ STL-like templated tree class. Copyright (C) 2001-2005 Kasper Peeters . */ /** \mainpage tree.hh \author Kasper Peeters \version 2.02 \date 12-Oct-2005 \see http://www.aei.mpg.de/~peekas/tree/ \see http://www.aei.mpg.de/~peekas/tree/ChangeLog The tree.hh library for C++ provides an STL-like container class for n-ary trees, templated over the data stored at the nodes. Various types of iterators are provided (post-order, pre-order, and others). Where possible the access methods are compatible with the STL or alternative algorithms are available. */ /* This program 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; version 2. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** \todo - New-style move members are not completely finished yet. - Fixed depth iterators do not iterate over the entire range if there are 'holes' in the tree. - If a range uses const iter_base& as end iterator, things will inevitably go wrong, because upcast from iter_base to a non-sibling_iter is incorrect. This upcast should be removed (and then all illegal uses as previously in 'equal' will be flagged by the compiler). This requires new copy constructors though. - There's a bug in replace(sibling_iterator, ...) when the ranges sit next to each other. Turned up in append_child(iter,iter) but has been avoided now. - "std::operator<" does not work correctly on our iterators, and for some reason a globally defined template operator< did not get picked up. Using a comparison class now, but this should be investigated. */ #ifndef tree_hh_ #define tree_hh_ #include #include #include #include #include // HP-style construct/destroy have gone from the standard, // so here is a copy. namespace kp { template void constructor(T1* p, T2& val) { new ((void *) p) T1(val); } template void constructor(T1* p) { new ((void *) p) T1; } template void destructor(T1* p) { p->~T1(); } }; /// A node in the tree, combining links to other nodes as well as the actual data. template class tree_node_ // size: 5*4=20 bytes (on 32 bit arch), can be reduced by 8. { public: tree_node_ *parent; tree_node_ *first_child, *last_child; tree_node_ *prev_sibling, *next_sibling; T data; }; // __attribute__((packed)); template < class T, class tree_node_allocator = std::allocator > > class tree { protected: typedef tree_node_ tree_node; public: /// Value of the data stored at a node. typedef T value_type; class iterator_base; class pre_order_iterator; class post_order_iterator; class sibling_iterator; tree(); tree(const T&); tree(const iterator_base&); tree(const tree&); ~tree(); void operator=(const tree&); /// Base class for iterators, only pointers stored, no traversal logic. #ifdef __SGI_STL_PORT class iterator_base : public stlport::bidirectional_iterator { #else class iterator_base { #endif public: typedef T value_type; typedef T* pointer; typedef T& reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef std::bidirectional_iterator_tag iterator_category; iterator_base(); iterator_base(tree_node *); T& operator*() const; T* operator->() const; /// When called, the next increment/decrement skips children of this node. void skip_children(); /// Number of children of the node pointed to by the iterator. unsigned int number_of_children() const; sibling_iterator begin() const; sibling_iterator end() const; tree_node *node; protected: bool skip_current_children_; }; /// Depth-first iterator, first accessing the node, then its children. class pre_order_iterator : public iterator_base { public: pre_order_iterator(); pre_order_iterator(tree_node *); pre_order_iterator(const iterator_base&); pre_order_iterator(const sibling_iterator&); bool operator==(const pre_order_iterator&) const; bool operator!=(const pre_order_iterator&) const; pre_order_iterator& operator++(); pre_order_iterator& operator--(); pre_order_iterator operator++(int); pre_order_iterator operator--(int); pre_order_iterator& operator+=(unsigned int); pre_order_iterator& operator-=(unsigned int); }; /// Depth-first iterator, first accessing the children, then the node itself. class post_order_iterator : public iterator_base { public: post_order_iterator(); post_order_iterator(tree_node *); post_order_iterator(const iterator_base&); post_order_iterator(const sibling_iterator&); bool operator==(const post_order_iterator&) const; bool operator!=(const post_order_iterator&) const; post_order_iterator& operator++(); post_order_iterator& operator--(); post_order_iterator operator++(int); post_order_iterator operator--(int); post_order_iterator& operator+=(unsigned int); post_order_iterator& operator-=(unsigned int); /// Set iterator to the first child as deep as possible down the tree. void descend_all(); }; /// The default iterator type throughout the tree class. typedef pre_order_iterator iterator; /// Iterator which traverses only the nodes at a given depth from the root. class fixed_depth_iterator : public iterator_base { public: fixed_depth_iterator(); fixed_depth_iterator(tree_node *); fixed_depth_iterator(const iterator_base&); fixed_depth_iterator(const sibling_iterator&); fixed_depth_iterator(const fixed_depth_iterator&); bool operator==(const fixed_depth_iterator&) const; bool operator!=(const fixed_depth_iterator&) const; fixed_depth_iterator& operator++(); fixed_depth_iterator& operator--(); fixed_depth_iterator operator++(int); fixed_depth_iterator operator--(int); fixed_depth_iterator& operator+=(unsigned int); fixed_depth_iterator& operator-=(unsigned int); tree_node *first_parent_; private: void set_first_parent_(); void find_leftmost_parent_(); }; /// Iterator which traverses only the nodes which are siblings of each other. class sibling_iterator : public iterator_base { public: sibling_iterator(); sibling_iterator(tree_node *); sibling_iterator(const sibling_iterator&); sibling_iterator(const iterator_base&); bool operator==(const sibling_iterator&) const; bool operator!=(const sibling_iterator&) const; sibling_iterator& operator++(); sibling_iterator& operator--(); sibling_iterator operator++(int); sibling_iterator operator--(int); sibling_iterator& operator+=(unsigned int); sibling_iterator& operator-=(unsigned int); tree_node *range_first() const; tree_node *range_last() const; tree_node *parent_; private: void set_parent_(); }; /// Return iterator to the beginning of the tree. inline pre_order_iterator begin() const; /// Return iterator to the end of the tree. inline pre_order_iterator end() const; /// Return post-order iterator to the beginning of the tree. post_order_iterator begin_post() const; /// Return post-order iterator to the end of the tree. post_order_iterator end_post() const; /// Return fixed-depth iterator to the first node at a given depth. fixed_depth_iterator begin_fixed(const iterator_base&, unsigned int) const; /// Return fixed-depth iterator to end of the nodes at given depth. fixed_depth_iterator end_fixed(const iterator_base&, unsigned int) const; /// Return sibling iterator to the first child of given node. sibling_iterator begin(const iterator_base&) const; /// Return sibling iterator to the end of the children of a given node. sibling_iterator end(const iterator_base&) const; /// Return iterator to the parent of a node. template iter parent(iter) const; /// Return iterator to the previous sibling of a node. template iter previous_sibling(iter) const; /// Return iterator to the next sibling of a node. template iter next_sibling(iter) const; /// Return iterator to the next node at a given depth. template iter next_at_same_depth(iter) const; /// Erase all nodes of the tree. void clear(); /// Erase element at position pointed to by iterator, return incremented iterator. template iter erase(iter); /// Erase all children of the node pointed to by iterator. void erase_children(const iterator_base&); /// Insert empty node as last child of node pointed to by position. template iter append_child(iter position); /// Insert node as last child of node pointed to by position. template iter append_child(iter position, const T& x); /// Append the node (plus its children) at other_position as a child of position. template iter append_child(iter position, iter other_position); /// Append the nodes in the from-to range (plus their children) as children of position. template iter append_children(iter position, sibling_iterator from, sibling_iterator to); /// Short-hand to insert topmost node in otherwise empty tree. pre_order_iterator set_head(const T& x); /// Insert node as previous sibling of node pointed to by position. template iter insert(iter position, const T& x); /// Specialisation of previous member. sibling_iterator insert(sibling_iterator position, const T& x); /// Insert node (with children) pointed to by subtree as previous sibling of node pointed to by position. template iter insert_subtree(iter position, const iterator_base& subtree); /// Insert node as next sibling of node pointed to by position. template iter insert_after(iter position, const T& x); /// Replace node at 'position' with other node (keeping same children); 'position' becomes invalid. template iter replace(iter position, const T& x); /// Replace node at 'position' with subtree starting at 'from' (do not erase subtree at 'from'); see above. template iter replace(iter position, const iterator_base& from); /// Replace string of siblings (plus their children) with copy of a new string (with children); see above sibling_iterator replace(sibling_iterator orig_begin, sibling_iterator orig_end, sibling_iterator new_begin, sibling_iterator new_end); /// Move all children of node at 'position' to be siblings, returns position. template iter flatten(iter position); /// Move nodes in range to be children of 'position'. template iter reparent(iter position, sibling_iterator begin, sibling_iterator end); /// Move all child nodes of 'from' to be children of 'position'. template iter reparent(iter position, iter from); /// Move 'source' node (plus its children) to become the next sibling of 'target'. template iter move_after(iter target, iter source); /// Move 'source' node (plus its children) to become the previous sibling of 'target'. template iter move_before(iter target, iter source); /// Move 'source' node (plus its children) to become the node at 'target' (erasing the node at 'target'). template iter move_ontop(iter target, iter source); /// Merge with other tree, creating new branches and leaves only if they are not already present. void merge(sibling_iterator, sibling_iterator, sibling_iterator, sibling_iterator, bool duplicate_leaves = false); /// Sort (std::sort only moves values of nodes, this one moves children as well). void sort(sibling_iterator from, sibling_iterator to, bool deep = false); template void sort(sibling_iterator from, sibling_iterator to, StrictWeakOrdering comp, bool deep = false); /// Compare two ranges of nodes (compares nodes as well as tree structure). template bool equal(const iter& one, const iter& two, const iter& three) const; template bool equal(const iter& one, const iter& two, const iter& three, BinaryPredicate) const; template bool equal_subtree(const iter& one, const iter& two) const; template bool equal_subtree(const iter& one, const iter& two, BinaryPredicate) const; /// Extract a new tree formed by the range of siblings plus all their children. tree subtree(sibling_iterator from, sibling_iterator to) const; void subtree(tree&, sibling_iterator from, sibling_iterator to) const; /// Exchange the node (plus subtree) with its sibling node (do nothing if no sibling present). void swap(sibling_iterator it); /// Count the total number of nodes. int size() const; /// Check if tree is empty. bool empty() const; /// Compute the depth to the root. int depth(const iterator_base&) const; /// Count the number of children of node at position. unsigned int number_of_children(const iterator_base&) const; /// Count the number of 'next' siblings of node at iterator. unsigned int number_of_siblings(const iterator_base&) const; /// Determine whether node at position is in the subtrees with root in the range. bool is_in_subtree(const iterator_base& position, const iterator_base& begin, const iterator_base& end) const; /// Determine whether the iterator is an 'end' iterator and thus not actually pointing to a node. bool is_valid(const iterator_base&) const; /// Determine the index of a node in the range of siblings to which it belongs. unsigned int index(sibling_iterator it) const; /// Inverse of 'index': return the n-th child of the node at position. sibling_iterator child(const iterator_base& position, unsigned int) const; /// Comparator class for iterators (compares the actual node content, not pointer values). class iterator_base_less { public: bool operator()(const typename tree::iterator_base& one, const typename tree::iterator_base& two) const { return one.node < two.node; } }; tree_node *head, *feet; // head/feet are always dummy; if an iterator points to them it is invalid private: tree_node_allocator alloc_; void head_initialise_(); void copy_(const tree& other); /// Comparator class for two nodes of a tree (used for sorting and searching). template class compare_nodes { public: compare_nodes(StrictWeakOrdering comp) : comp_(comp) {}; bool operator()(const tree_node *a, const tree_node *b) { static StrictWeakOrdering comp; return comp(a->data, b->data); } private: StrictWeakOrdering comp_; }; }; //template //class iterator_base_less { // public: // bool operator()(const typename tree::iterator_base& one, // const typename tree::iterator_base& two) const // { // txtout << "operatorclass<" << one.node < two.node << std::endl; // return one.node < two.node; // } //}; //template //bool operator<(const typename tree::iterator& one, // const typename tree::iterator& two) // { // txtout << "operator< " << one.node < two.node << std::endl; // if(one.node < two.node) return true; // return false; // } template bool operator>(const typename tree::iterator_base& one, const typename tree::iterator_base& two) { if (one.node > two.node) return true; return false; } // Tree template tree::tree() { head_initialise_(); } template tree::tree(const T& x) { head_initialise_(); set_head(x); } template tree::tree(const iterator_base& other) { head_initialise_(); set_head((*other)); replace(begin(), other); } template tree::~tree() { clear(); alloc_.deallocate(head, 1); alloc_.deallocate(feet, 1); } template void tree::head_initialise_() { head = alloc_.allocate(1, 0); // MSVC does not have default second argument feet = alloc_.allocate(1, 0); head->parent = 0; head->first_child = 0; head->last_child = 0; head->prev_sibling = 0; //head; head->next_sibling = feet; //head; feet->parent = 0; feet->first_child = 0; feet->last_child = 0; feet->prev_sibling = head; feet->next_sibling = 0; } template void tree::operator=(const tree& other) { copy_(other); } template tree::tree(const tree& other) { head_initialise_(); copy_(other); } template void tree::copy_(const tree& other) { clear(); pre_order_iterator it = other.begin(), to = begin(); while (it != other.end()) { to = insert(to, (*it)); it.skip_children(); ++it; } to = begin(); it = other.begin(); while (it != other.end()) { to = replace(to, it); to.skip_children(); it.skip_children(); ++to; ++it; } } template void tree::clear() { if (head) while (head->next_sibling != feet) erase(pre_order_iterator(head->next_sibling)); } template void tree::erase_children(const iterator_base& it) { tree_node *cur = it.node->first_child; tree_node *prev = 0; while (cur != 0) { prev = cur; cur = cur->next_sibling; erase_children(pre_order_iterator(prev)); kp::destructor(&prev->data); alloc_.deallocate(prev, 1); } it.node->first_child = 0; it.node->last_child = 0; } template template iter tree::erase(iter it) { tree_node *cur = it.node; assert(cur != head); iter ret = it; ret.skip_children(); ++ret; erase_children(it); if (cur->prev_sibling == 0) { cur->parent->first_child = cur->next_sibling; } else { cur->prev_sibling->next_sibling = cur->next_sibling; } if (cur->next_sibling == 0) { cur->parent->last_child = cur->prev_sibling; } else { cur->next_sibling->prev_sibling = cur->prev_sibling; } kp::destructor(&cur->data); alloc_.deallocate(cur, 1); return ret; } template typename tree::pre_order_iterator tree::begin() const { return pre_order_iterator(head->next_sibling); } template typename tree::pre_order_iterator tree::end() const { return pre_order_iterator(feet); } template typename tree::post_order_iterator tree::begin_post() const { tree_node *tmp = head->next_sibling; if (tmp != feet) { while (tmp->first_child) tmp = tmp->first_child; } return post_order_iterator(tmp); } template typename tree::post_order_iterator tree::end_post() const { return post_order_iterator(feet); } template typename tree::fixed_depth_iterator tree::begin_fixed(const iterator_base& pos, unsigned int dp) const { tree_node *tmp = pos.node; unsigned int curdepth = 0; while (curdepth < dp) // go down one level { while (tmp->first_child == 0) { tmp = tmp->next_sibling; if (tmp == 0) throw std::range_error("tree: begin_fixed out of range"); } tmp = tmp->first_child; ++curdepth; } return tmp; } template typename tree::fixed_depth_iterator tree::end_fixed(const iterator_base& pos, unsigned int dp) const { assert(1 == 0); // FIXME: not correct yet tree_node *tmp = pos.node; unsigned int curdepth = 1; while (curdepth < dp) // go down one level { while (tmp->first_child == 0) { tmp = tmp->next_sibling; if (tmp == 0) throw std::range_error("tree: end_fixed out of range"); } tmp = tmp->first_child; ++curdepth; } return tmp; } template typename tree::sibling_iterator tree::begin(const iterator_base& pos) const { if (pos.node->first_child == 0) { return end(pos); } return pos.node->first_child; } template typename tree::sibling_iterator tree::end(const iterator_base& pos) const { sibling_iterator ret(0); ret.parent_ = pos.node; return ret; } template template iter tree::parent(iter position) const { assert(position.node != 0); return iter(position.node->parent); } template template iter tree::previous_sibling(iter position) const { assert(position.node != 0); iter ret(position); ret.node = position.node->prev_sibling; return ret; } template template iter tree::next_sibling(iter position) const { assert(position.node != 0); iter ret(position); ret.node = position.node->next_sibling; return ret; } template template iter tree::next_at_same_depth(iter position) const { assert(position.node != 0); iter ret(position); if (position.node->next_sibling) { ret.node = position.node->next_sibling; } else { int relative_depth = 0; upper: do { ret.node = ret.node->parent; if (ret.node == 0) return ret; --relative_depth; } while (ret.node->next_sibling == 0); lower: ret.node = ret.node->next_sibling; while (ret.node->first_child == 0) { if (ret.node->next_sibling == 0) goto upper; ret.node = ret.node->next_sibling; if (ret.node == 0) return ret; } while (relative_depth < 0 && ret.node->first_child != 0) { ret.node = ret.node->first_child; ++relative_depth; } if (relative_depth < 0) { if (ret.node->next_sibling == 0) goto upper; else goto lower; } } return ret; } template template iter tree::append_child(iter position) { assert(position.node != head); tree_node* tmp = alloc_.allocate(1, 0); kp::constructor(&tmp->data); tmp->first_child = 0; tmp->last_child = 0; tmp->parent = position.node; if (position.node->last_child != 0) { position.node->last_child->next_sibling = tmp; } else { position.node->first_child = tmp; } tmp->prev_sibling = position.node->last_child; position.node->last_child = tmp; tmp->next_sibling = 0; return tmp; } template template iter tree::append_child(iter position, const T& x) { // If your program fails here you probably used 'append_child' to add the top // node to an empty tree. From version 1.45 the top element should be added // using 'insert'. See the documentation for further information, and sorry about // the API change. assert(position.node != head); tree_node* tmp = alloc_.allocate(1, 0); kp::constructor(&tmp->data, x); tmp->first_child = 0; tmp->last_child = 0; tmp->parent = position.node; if (position.node->last_child != 0) { position.node->last_child->next_sibling = tmp; } else { position.node->first_child = tmp; } tmp->prev_sibling = position.node->last_child; position.node->last_child = tmp; tmp->next_sibling = 0; return tmp; } template template iter tree::append_child(iter position, iter other) { assert(position.node != head); sibling_iterator aargh = append_child(position, value_type()); return replace(aargh, other); } template template iter tree::append_children(iter position, sibling_iterator from, sibling_iterator to) { iter ret = from; while (from != to) { insert_subtree(position.end(), from); ++from; } return ret; } template typename tree::pre_order_iterator tree::set_head(const T& x) { assert(head->next_sibling == feet); return insert(iterator(feet), x); } template template iter tree::insert(iter position, const T& x) { if (position.node == 0) { position.node = feet; // Backward compatibility: when calling insert on a null node, // insert before the feet. } tree_node* tmp = alloc_.allocate(1, 0); kp::constructor(&tmp->data, x); tmp->first_child = 0; tmp->last_child = 0; tmp->parent = position.node->parent; tmp->next_sibling = position.node; tmp->prev_sibling = position.node->prev_sibling; position.node->prev_sibling = tmp; if (tmp->prev_sibling == 0) { if (tmp->parent) // when inserting nodes at the head, there is no parent tmp->parent->first_child = tmp; } else tmp->prev_sibling->next_sibling = tmp; return tmp; } template typename tree::sibling_iterator tree::insert(sibling_iterator position, const T& x) { tree_node* tmp = alloc_.allocate(1, 0); kp::constructor(&tmp->data, x); tmp->first_child = 0; tmp->last_child = 0; tmp->next_sibling = position.node; if (position.node == 0) // iterator points to end of a subtree { tmp->parent = position.parent_; tmp->prev_sibling = position.range_last(); tmp->parent->last_child = tmp; } else { tmp->parent = position.node->parent; tmp->prev_sibling = position.node->prev_sibling; position.node->prev_sibling = tmp; } if (tmp->prev_sibling == 0) { if (tmp->parent) // when inserting nodes at the head, there is no parent tmp->parent->first_child = tmp; } else tmp->prev_sibling->next_sibling = tmp; return tmp; } template template iter tree::insert_after(iter position, const T& x) { tree_node* tmp = alloc_.allocate(1, 0); kp::constructor(&tmp->data, x); tmp->first_child = 0; tmp->last_child = 0; tmp->parent = position.node->parent; tmp->prev_sibling = position.node; tmp->next_sibling = position.node->next_sibling; position.node->next_sibling = tmp; if (tmp->next_sibling == 0) { if (tmp->parent) // when inserting nodes at the head, there is no parent tmp->parent->last_child = tmp; } else { tmp->next_sibling->prev_sibling = tmp; } return tmp; } template template iter tree::insert_subtree(iter position, const iterator_base& subtree) { // insert dummy iter it = insert(position, value_type()); // replace dummy with subtree return replace(it, subtree); } // template // template // iter tree::insert_subtree(sibling_iterator position, iter subtree) // { // // insert dummy // iter it(insert(position, value_type())); // // replace dummy with subtree // return replace(it, subtree); // } template template iter tree::replace(iter position, const T& x) { kp::destructor(&position.node->data); kp::constructor(&position.node->data, x); return position; } template template iter tree::replace(iter position, const iterator_base& from) { assert(position.node != head); tree_node *current_from = from.node; tree_node *start_from = from.node; tree_node *current_to = position.node; // replace the node at position with head of the replacement tree at from erase_children(position); tree_node* tmp = alloc_.allocate(1, 0); kp::constructor(&tmp->data, (*from)); tmp->first_child = 0; tmp->last_child = 0; if (current_to->prev_sibling == 0) { current_to->parent->first_child = tmp; } else { current_to->prev_sibling->next_sibling = tmp; } tmp->prev_sibling = current_to->prev_sibling; if (current_to->next_sibling == 0) { current_to->parent->last_child = tmp; } else { current_to->next_sibling->prev_sibling = tmp; } tmp->next_sibling = current_to->next_sibling; tmp->parent = current_to->parent; kp::destructor(¤t_to->data); alloc_.deallocate(current_to, 1); current_to = tmp; // only at this stage can we fix 'last' tree_node *last = from.node->next_sibling; pre_order_iterator toit = tmp; // copy all children do { assert(current_from != 0); if (current_from->first_child != 0) { current_from = current_from->first_child; toit = append_child(toit, current_from->data); } else { while (current_from->next_sibling == 0 && current_from != start_from) { current_from = current_from->parent; toit = parent(toit); assert(current_from != 0); } current_from = current_from->next_sibling; if (current_from != last) { toit = append_child(parent(toit), current_from->data); } } } while (current_from != last); return current_to; } template typename tree::sibling_iterator tree::replace( sibling_iterator orig_begin, sibling_iterator orig_end, sibling_iterator new_begin, sibling_iterator new_end) { tree_node *orig_first = orig_begin.node; tree_node *new_first = new_begin.node; tree_node *orig_last = orig_first; while ((++orig_begin) != orig_end) orig_last = orig_last->next_sibling; tree_node *new_last = new_first; while ((++new_begin) != new_end) new_last = new_last->next_sibling; // insert all siblings in new_first..new_last before orig_first bool first = true; pre_order_iterator ret; while (1 == 1) { pre_order_iterator tt = insert_subtree(pre_order_iterator(orig_first), pre_order_iterator(new_first)); if (first) { ret = tt; first = false; } if (new_first == new_last) break; new_first = new_first->next_sibling; } // erase old range of siblings bool last = false; tree_node *next = orig_first; while (1 == 1) { if (next == orig_last) last = true; next = next->next_sibling; erase((pre_order_iterator)orig_first); if (last) break; orig_first = next; } return ret; } template template iter tree::flatten(iter position) { if (position.node->first_child == 0) return position; tree_node *tmp = position.node->first_child; while (tmp) { tmp->parent = position.node->parent; tmp = tmp->next_sibling; } if (position.node->next_sibling) { position.node->last_child->next_sibling = position.node->next_sibling; position.node->next_sibling->prev_sibling = position.node->last_child; } else { position.node->parent->last_child = position.node->last_child; } position.node->next_sibling = position.node->first_child; position.node->next_sibling->prev_sibling = position.node; position.node->first_child = 0; position.node->last_child = 0; return position; } template template iter tree::reparent(iter position, sibling_iterator begin, sibling_iterator end) { tree_node *first = begin.node; tree_node *last = first; if (begin == end) return begin; // determine last node while ((++begin) != end) { last = last->next_sibling; } // move subtree if (first->prev_sibling == 0) { first->parent->first_child = last->next_sibling; } else { first->prev_sibling->next_sibling = last->next_sibling; } if (last->next_sibling == 0) { last->parent->last_child = first->prev_sibling; } else { last->next_sibling->prev_sibling = first->prev_sibling; } if (position.node->first_child == 0) { position.node->first_child = first; position.node->last_child = last; first->prev_sibling = 0; } else { position.node->last_child->next_sibling = first; first->prev_sibling = position.node->last_child; position.node->last_child = last; } last->next_sibling = 0; tree_node *pos = first; while (1 == 1) { pos->parent = position.node; if (pos == last) break; pos = pos->next_sibling; } return first; } template template iter tree::reparent(iter position, iter from) { if (from.node->first_child == 0) return position; return reparent(position, from.node->first_child, end(from)); } template template iter tree::move_after(iter target, iter source) { tree_node *dst = target.node; tree_node *src = source.node; assert(dst); assert(src); if (dst == src) return source; // take src out of the tree if (src->prev_sibling != 0) src->prev_sibling->next_sibling = src->next_sibling; else src->parent->first_child = src->next_sibling; if (src->next_sibling != 0) src->next_sibling->prev_sibling = src->prev_sibling; else src->parent->last_child = src->prev_sibling; // connect it to the new point if (dst->next_sibling != 0) dst->next_sibling->prev_sibling = src; else dst->parent->last_child = src; src->next_sibling = dst->next_sibling; dst->next_sibling = src; src->prev_sibling = dst; src->parent = dst->parent; return src; } template template iter tree::move_before(iter target, iter source) { tree_node *dst = target.node; tree_node *src = source.node; assert(dst); assert(src); if (dst == src) return source; // take src out of the tree if (src->prev_sibling != 0) src->prev_sibling->next_sibling = src->next_sibling; else src->parent->first_child = src->next_sibling; if (src->next_sibling != 0) src->next_sibling->prev_sibling = src->prev_sibling; else src->parent->last_child = src->prev_sibling; // connect it to the new point if (dst->prev_sibling != 0) dst->prev_sibling->next_sibling = src; else dst->parent->first_child = src; src->prev_sibling = dst->prev_sibling; dst->prev_sibling = src; src->next_sibling = dst; src->parent = dst->parent; return src; } template template iter tree::move_ontop(iter target, iter source) { tree_node *dst = target.node; tree_node *src = source.node; assert(dst); assert(src); if (dst == src) return source; // remember connection points tree_node *b_prev_sibling = dst->prev_sibling; tree_node *b_next_sibling = dst->next_sibling; tree_node *b_parent = dst->parent; // remove target erase(target); // take src out of the tree if (src->prev_sibling != 0) src->prev_sibling->next_sibling = src->next_sibling; else src->parent->first_child = src->next_sibling; if (src->next_sibling != 0) src->next_sibling->prev_sibling = src->prev_sibling; else src->parent->last_child = src->prev_sibling; // connect it to the new point if (b_prev_sibling != 0) b_prev_sibling->next_sibling = src; else b_parent->first_child = src; if (b_next_sibling != 0) b_next_sibling->prev_sibling = src; else b_parent->last_child = src; src->prev_sibling = b_prev_sibling; src->next_sibling = b_next_sibling; src->parent = b_parent; return src; } template void tree::merge(sibling_iterator to1, sibling_iterator to2, sibling_iterator from1, sibling_iterator from2, bool duplicate_leaves) { sibling_iterator fnd; while (from1 != from2) { if ((fnd = std::find(to1, to2, (*from1))) != to2) // element found { if (from1.begin() == from1.end()) // full depth reached { if (duplicate_leaves) append_child(parent(to1), (*from1)); } else // descend further { merge(fnd.begin(), fnd.end(), from1.begin(), from1.end(), duplicate_leaves); } } else // element missing { insert_subtree(to2, from1); } ++from1; } } template void tree::sort(sibling_iterator from, sibling_iterator to, bool deep) { std::less comp; sort(from, to, comp, deep); } template template void tree::sort(sibling_iterator from, sibling_iterator to, StrictWeakOrdering comp, bool deep) { if (from == to) return; // make list of sorted nodes // CHECK: if multiset stores equivalent nodes in the order in which they // are inserted, then this routine should be called 'stable_sort'. std::multiset > nodes(comp); sibling_iterator it = from, it2 = to; while (it != to) { nodes.insert(it.node); ++it; } // reassemble --it2; // prev and next are the nodes before and after the sorted range tree_node *prev = from.node->prev_sibling; tree_node *next = it2.node->next_sibling; typename std::multiset >::iterator nit = nodes.begin(), eit = nodes.end(); if (prev == 0) { if ((*nit)->parent != 0) // to catch "sorting the head" situations, when there is no parent (*nit)->parent->first_child = (*nit); } else prev->next_sibling = (*nit); --eit; while (nit != eit) { (*nit)->prev_sibling = prev; if (prev) prev->next_sibling = (*nit); prev = (*nit); ++nit; } // prev now points to the last-but-one node in the sorted range if (prev) prev->next_sibling = (*eit); // eit points to the last node in the sorted range. (*eit)->next_sibling = next; (*eit)->prev_sibling = prev; // missed in the loop above if (next == 0) { if ((*eit)->parent != 0) // to catch "sorting the head" situations, when there is no parent (*eit)->parent->last_child = (*eit); } else next->prev_sibling = (*eit); if (deep) // sort the children of each node too { sibling_iterator bcs(*nodes.begin()); sibling_iterator ecs(*eit); ++ecs; while (bcs != ecs) { sort(begin(bcs), end(bcs), comp, deep); ++bcs; } } } template template bool tree::equal(const iter& one_, const iter& two, const iter& three_) const { std::equal_to comp; return equal(one_, two, three_, comp); } template template bool tree::equal_subtree(const iter& one_, const iter& two_) const { std::equal_to comp; return equal_subtree(one_, two_, comp); } template template bool tree::equal(const iter& one_, const iter& two, const iter& three_, BinaryPredicate fun) const { pre_order_iterator one(one_), three(three_); // if(one==two && is_valid(three) && three.number_of_children()!=0) // return false; while (one != two && is_valid(three)) { if (!fun(*one, *three)) return false; if (one.number_of_children() != three.number_of_children()) return false; ++one; ++three; } return true; } template template bool tree::equal_subtree(const iter& one_, const iter& two_, BinaryPredicate fun) const { pre_order_iterator one(one_), two(two_); if (!fun(*one, *two)) return false; if (number_of_children(one) != number_of_children(two)) return false; return equal(begin(one), end(one), begin(two), fun); } template tree tree::subtree(sibling_iterator from, sibling_iterator to) const { tree tmp; tmp.set_head(value_type()); tmp.replace(tmp.begin(), tmp.end(), from, to); return tmp; } template void tree::subtree(tree& tmp, sibling_iterator from, sibling_iterator to) const { tmp.set_head(value_type()); tmp.replace(tmp.begin(), tmp.end(), from, to); } template int tree::size() const { int i = 0; pre_order_iterator it = begin(), eit = end(); while (it != eit) { ++i; ++it; } return i; } template bool tree::empty() const { pre_order_iterator it = begin(), eit = end(); return (it == eit); } template int tree::depth(const iterator_base& it) const { tree_node* pos = it.node; assert(pos != 0); int ret = 0; while (pos->parent != 0) { pos = pos->parent; ++ret; } return ret; } template unsigned int tree::number_of_children(const iterator_base& it) const { tree_node *pos = it.node->first_child; if (pos == 0) return 0; unsigned int ret = 1; // while(pos!=it.node->last_child) { // ++ret; // pos=pos->next_sibling; // } while ((pos = pos->next_sibling)) ++ret; return ret; } template unsigned int tree::number_of_siblings(const iterator_base& it) const { tree_node *pos = it.node; unsigned int ret = 0; while (pos->next_sibling && pos->next_sibling != head && pos->next_sibling != feet) { ++ret; pos = pos->next_sibling; } return ret; } template void tree::swap(sibling_iterator it) { tree_node *nxt = it.node->next_sibling; if (nxt) { if (it.node->prev_sibling) it.node->prev_sibling->next_sibling = nxt; else it.node->parent->first_child = nxt; nxt->prev_sibling = it.node->prev_sibling; tree_node *nxtnxt = nxt->next_sibling; if (nxtnxt) nxtnxt->prev_sibling = it.node; else it.node->parent->last_child = it.node; nxt->next_sibling = it.node; it.node->prev_sibling = nxt; it.node->next_sibling = nxtnxt; } } // template // tree::iterator tree::find_subtree( // sibling_iterator subfrom, sibling_iterator subto, iterator from, iterator to, // BinaryPredicate fun) const // { // assert(1==0); // this routine is not finished yet. // while(from!=to) { // if(fun(*subfrom, *from)) { // // } // } // return to; // } template bool tree::is_in_subtree(const iterator_base& it, const iterator_base& begin, const iterator_base& end) const { // FIXME: this should be optimised. pre_order_iterator tmp = begin; while (tmp != end) { if (tmp == it) return true; ++tmp; } return false; } template bool tree::is_valid(const iterator_base& it) const { if (it.node == 0 || it.node == feet) return false; else return true; } template unsigned int tree::index(sibling_iterator it) const { unsigned int ind = 0; if (it.node->parent == 0) { while (it.node->prev_sibling != head) { it.node = it.node->prev_sibling; ++ind; } } else { while (it.node->prev_sibling != 0) { it.node = it.node->prev_sibling; ++ind; } } return ind; } template typename tree::sibling_iterator tree::child(const iterator_base& it, unsigned int num) const { tree_node *tmp = it.node->first_child; while (num--) { assert(tmp != 0); tmp = tmp->next_sibling; } return tmp; } // Iterator base template tree::iterator_base::iterator_base() : node(0), skip_current_children_(false) { } template tree::iterator_base::iterator_base(tree_node *tn) : node(tn), skip_current_children_(false) { } template T& tree::iterator_base::operator*() const { return node->data; } template T* tree::iterator_base::operator->() const { return &(node->data); } template bool tree::post_order_iterator::operator!=(const post_order_iterator& other) const { if (other.node != this->node) return true; else return false; } template bool tree::post_order_iterator::operator==(const post_order_iterator& other) const { if (other.node == this->node) return true; else return false; } template bool tree::pre_order_iterator::operator!=(const pre_order_iterator& other) const { if (other.node != this->node) return true; else return false; } template bool tree::pre_order_iterator::operator==(const pre_order_iterator& other) const { if (other.node == this->node) return true; else return false; } template bool tree::sibling_iterator::operator!=(const sibling_iterator& other) const { if (other.node != this->node) return true; else return false; } template bool tree::sibling_iterator::operator==(const sibling_iterator& other) const { if (other.node == this->node) return true; else return false; } template typename tree::sibling_iterator tree::iterator_base::begin() const { sibling_iterator ret(node->first_child); ret.parent_ = this->node; return ret; } template typename tree::sibling_iterator tree::iterator_base::end() const { sibling_iterator ret(0); ret.parent_ = node; return ret; } template void tree::iterator_base::skip_children() { skip_current_children_ = true; } template unsigned int tree::iterator_base::number_of_children() const { tree_node *pos = node->first_child; if (pos == 0) return 0; unsigned int ret = 1; while (pos != node->last_child) { ++ret; pos = pos->next_sibling; } return ret; } // Pre-order iterator template tree::pre_order_iterator::pre_order_iterator() : iterator_base(0) { } template tree::pre_order_iterator::pre_order_iterator(tree_node *tn) : iterator_base(tn) { } template tree::pre_order_iterator::pre_order_iterator(const iterator_base &other) : iterator_base(other.node) { } template tree::pre_order_iterator::pre_order_iterator(const sibling_iterator& other) : iterator_base(other.node) { if (this->node == 0) { if (other.range_last() != 0) this->node = other.range_last(); else this->node = other.parent_; this->skip_children(); ++(*this); } } template typename tree::pre_order_iterator& tree::pre_order_iterator::operator++() { assert(this->node != 0); if (!this->skip_current_children_ && this->node->first_child != 0) { this->node = this->node->first_child; } else { this->skip_current_children_ = false; while (this->node->next_sibling == 0) { this->node = this->node->parent; if (this->node == 0) return *this; } this->node = this->node->next_sibling; } return *this; } template typename tree::pre_order_iterator& tree::pre_order_iterator::operator--() { assert(this->node != 0); if (this->node->prev_sibling) { this->node = this->node->prev_sibling; while (this->node->last_child) this->node = this->node->last_child; } else { this->node = this->node->parent; if (this->node == 0) return *this; } return *this; } template typename tree::pre_order_iterator tree::pre_order_iterator::operator++(int n) { pre_order_iterator copy = *this; ++(*this); return copy; } template typename tree::pre_order_iterator tree::pre_order_iterator::operator--(int n) { pre_order_iterator copy = *this; --(*this); return copy; } template typename tree::pre_order_iterator& tree::pre_order_iterator::operator+=(unsigned int num) { while (num > 0) { ++(*this); --num; } return (*this); } template typename tree::pre_order_iterator& tree::pre_order_iterator::operator-=(unsigned int num) { while (num > 0) { --(*this); --num; } return (*this); } // Post-order iterator template tree::post_order_iterator::post_order_iterator() : iterator_base(0) { } template tree::post_order_iterator::post_order_iterator(tree_node *tn) : iterator_base(tn) { } template tree::post_order_iterator::post_order_iterator(const iterator_base &other) : iterator_base(other.node) { } template tree::post_order_iterator::post_order_iterator(const sibling_iterator& other) : iterator_base(other.node) { if (this->node == 0) { if (other.range_last() != 0) this->node = other.range_last(); else this->node = other.parent_; this->skip_children(); ++(*this); } } template typename tree::post_order_iterator& tree::post_order_iterator::operator++() { assert(this->node != 0); if (this->node->next_sibling == 0) { this->node = this->node->parent; this->skip_current_children_ = false; } else { this->node = this->node->next_sibling; if (this->skip_current_children_) { this->skip_current_children_ = false; } else { while (this->node->first_child) this->node = this->node->first_child; } } return *this; } template typename tree::post_order_iterator& tree::post_order_iterator::operator--() { assert(this->node != 0); if (this->skip_current_children_ || this->node->last_child == 0) { this->skip_current_children_ = false; while (this->node->prev_sibling == 0) this->node = this->node->parent; this->node = this->node->prev_sibling; } else { this->node = this->node->last_child; } return *this; } template typename tree::post_order_iterator tree::post_order_iterator::operator++(int) { post_order_iterator copy = *this; ++(*this); return copy; } template typename tree::post_order_iterator tree::post_order_iterator::operator--(int) { post_order_iterator copy = *this; --(*this); return copy; } template typename tree::post_order_iterator& tree::post_order_iterator::operator+=(unsigned int num) { while (num > 0) { ++(*this); --num; } return (*this); } template typename tree::post_order_iterator& tree::post_order_iterator::operator-=(unsigned int num) { while (num > 0) { --(*this); --num; } return (*this); } template void tree::post_order_iterator::descend_all() { assert(this->node != 0); while (this->node->first_child) this->node = this->node->first_child; } // Fixed depth iterator template tree::fixed_depth_iterator::fixed_depth_iterator() : iterator_base() { set_first_parent_(); } template tree::fixed_depth_iterator::fixed_depth_iterator(tree_node *tn) : iterator_base(tn) { set_first_parent_(); } template tree::fixed_depth_iterator::fixed_depth_iterator(const iterator_base& other) : iterator_base(other.node) { set_first_parent_(); } template tree::fixed_depth_iterator::fixed_depth_iterator(const sibling_iterator& other) : iterator_base(other.node), first_parent_(other.parent_) { find_leftmost_parent_(); } template tree::fixed_depth_iterator::fixed_depth_iterator(const fixed_depth_iterator& other) : iterator_base(other.node), first_parent_(other.first_parent_) { } template void tree::fixed_depth_iterator::set_first_parent_() { return; // FIXME: we do not use first_parent_ yet, and it actually needs some serious reworking if // it is ever to work at the 'head' level. first_parent_ = 0; if (this->node == 0) return; if (this->node->parent != 0) first_parent_ = this->node->parent; if (first_parent_) find_leftmost_parent_(); } template void tree::fixed_depth_iterator::find_leftmost_parent_() { return; // FIXME: see 'set_first_parent()' tree_node *tmppar = first_parent_; while (tmppar->prev_sibling) { tmppar = tmppar->prev_sibling; if (tmppar->first_child) first_parent_ = tmppar; } } template typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator++() { assert(this->node != 0); if (this->node->next_sibling) { this->node = this->node->next_sibling; } else { int relative_depth = 0; upper: do { this->node = this->node->parent; if (this->node == 0) return *this; --relative_depth; } while (this->node->next_sibling == 0); lower: this->node = this->node->next_sibling; while (this->node->first_child == 0) { if (this->node->next_sibling == 0) goto upper; this->node = this->node->next_sibling; if (this->node == 0) return *this; } while (relative_depth < 0 && this->node->first_child != 0) { this->node = this->node->first_child; ++relative_depth; } if (relative_depth < 0) { if (this->node->next_sibling == 0) goto upper; else goto lower; } } return *this; // if(this->node->next_sibling!=0) { // this->node=this->node->next_sibling; // assert(this->node!=0); // if(this->node->parent==0 && this->node->next_sibling==0) // feet element // this->node=0; // } // else { // tree_node *par=this->node->parent; // do { // par=par->next_sibling; // if(par==0) { // FIXME: need to keep track of this! // this->node=0; // return *this; // } // } while(par->first_child==0); // this->node=par->first_child; // } return *this; } template typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator--() { assert(this->node != 0); if (this->node->prev_sibling != 0) { this->node = this->node->prev_sibling; assert(this->node != 0); if (this->node->parent == 0 && this->node->prev_sibling == 0) // head element this->node = 0; } else { tree_node *par = this->node->parent; do { par = par->prev_sibling; if (par == 0) // FIXME: need to keep track of this! { this->node = 0; return *this; } } while (par->last_child == 0); this->node = par->last_child; } return *this; } template typename tree::fixed_depth_iterator tree::fixed_depth_iterator::operator++(int) { fixed_depth_iterator copy = *this; ++(*this); return copy; } template typename tree::fixed_depth_iterator tree::fixed_depth_iterator::operator--(int) { fixed_depth_iterator copy = *this; --(*this); return copy; } template typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator-=(unsigned int num) { while (num > 0) { --(*this); --(num); } return (*this); } template typename tree::fixed_depth_iterator& tree::fixed_depth_iterator::operator+=(unsigned int num) { while (num > 0) { ++(*this); --(num); } return *this; } // FIXME: add the other members of fixed_depth_iterator. // Sibling iterator template tree::sibling_iterator::sibling_iterator() : iterator_base() { set_parent_(); } template tree::sibling_iterator::sibling_iterator(tree_node *tn) : iterator_base(tn) { set_parent_(); } template tree::sibling_iterator::sibling_iterator(const iterator_base& other) : iterator_base(other.node) { set_parent_(); } template tree::sibling_iterator::sibling_iterator(const sibling_iterator& other) : iterator_base(other), parent_(other.parent_) { } template void tree::sibling_iterator::set_parent_() { parent_ = 0; if (this->node == 0) return; if (this->node->parent != 0) parent_ = this->node->parent; } template typename tree::sibling_iterator& tree::sibling_iterator::operator++() { if (this->node) this->node = this->node->next_sibling; return *this; } template typename tree::sibling_iterator& tree::sibling_iterator::operator--() { if (this->node) this->node = this->node->prev_sibling; else { assert(parent_); this->node = parent_->last_child; } return *this; } template typename tree::sibling_iterator tree::sibling_iterator::operator++(int) { sibling_iterator copy = *this; ++(*this); return copy; } template typename tree::sibling_iterator tree::sibling_iterator::operator--(int) { sibling_iterator copy = *this; --(*this); return copy; } template typename tree::sibling_iterator& tree::sibling_iterator::operator+=(unsigned int num) { while (num > 0) { ++(*this); --num; } return (*this); } template typename tree::sibling_iterator& tree::sibling_iterator::operator-=(unsigned int num) { while (num > 0) { --(*this); --num; } return (*this); } template typename tree::tree_node *tree::sibling_iterator::range_first() const { tree_node *tmp = parent_->first_child; return tmp; } template typename tree::tree_node *tree::sibling_iterator::range_last() const { return parent_->last_child; } #endif // Local variables: // default-tab-width: 3 // End: