Import Geant4 8.1.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 14:44:26 +02:00
parent 8a51e0bc40
commit 216a75eeb1
8717 changed files with 360418 additions and 141343 deletions
@@ -0,0 +1 @@
Troy A. Johnson, tajohnson@ieee.org
@@ -0,0 +1,27 @@
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,37 @@
Version 0.5.0, 1/2/2006
- Realized that assignment to *i for const_iterators was
being allowed. Fixed.
- Forced instantiation of whole template and caught
several typos (iterator in place of const_iterator, etc.)
- Can now find the size of subtrees using a size() method
of iterator or const_iterator
- i += n for sibling_iterators
- Added range constructor to build n-ary trees
- Allow conversion from iterator to const_iterator
- Added height() and height_leftmost() tree methods
- First serious attempt at pointer specialization. It is
disabled by default because it is incomplete and programs
with only a few types of pointer trees will get larger.
If you have many different types of trees, then the program
size should increase less with specialization enabled.
Suggestions on the best way to implement specialization
are welcome.
Version 0.2.1, 12/17/2005
- Compatible with gcc 4.0
- Pruning for const_preorder_iterator
- Added depth counter for iterators
- Added addition operator to sibling_iterators so that you can
do stuff like j = i + 1.
Version 0.2.0, 04/05/2005
- Now compatible with gcc 3.4
- In between 0.1.0 and 0.2.0, the tree class saw
extensive use representing parse trees and various
other tree structures in my own programs. Remaining
bugs are likely in methods I don't use very often
but provided because they seemed useful.
Version 0.1.0, 07/18/2003
- very general tree template
- STL compatible
@@ -0,0 +1,89 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
class bfs_iterator : public virtual iterator
{
friend class tree;
private:
std::list<tree_node<N>*> queue;
typedef bool (*PruningPredicate)(const iterator& iter);
PruningPredicate prune_pred;
explicit bfs_iterator(tree_node<N>* current) : iterator(current), prune_pred(NULL) { }
public:
bfs_iterator(void) : prune_pred(NULL) { }
bfs_iterator(const iterator& iter) : iterator(iter), prune_pred(NULL) { }
bfs_iterator endBfs(void) { return bfs_iterator(NULL); }
bfs_iterator& operator ++ (void)
{
/* this line necessary for g++ 3.4 onward */
tree_node<N>*& current = this->current;
assert(current != NULL);
if (prune_pred == NULL || !prune_pred(*this))
{
for (tree_node<N>* p = current->first_child;
p != NULL; p = p->next_sibling)
{
queue.push_front(p);
}
}
if (queue.empty())
{
current = NULL;
}
else
{
current = queue.back();
queue.pop_back();
}
return *this;
}
/** When the iterator points to a node, and the pruning predicate
* returns true, the children of the node are not added to the BFS
* queue. True means prune everything beneath the node passed
* to the predicate. A NULL predicate disables pruning. */
void pruneOn(PruningPredicate prune_pred)
{
this->prune_pred = prune_pred;
}
};
@@ -0,0 +1,74 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
class const_bfs_iterator : public virtual const_iterator
{
friend class tree;
private:
std::list<tree_node<N>*> queue;
explicit const_bfs_iterator(tree_node<N>* current) : const_iterator(current) { }
public:
const_bfs_iterator(void) { }
const_bfs_iterator(const const_iterator& iter) : const_iterator(iter) { }
const_bfs_iterator endBfs(void) const { return const_bfs_iterator(NULL); }
const_bfs_iterator& operator ++ (void)
{
/* this line necessary for g++ 3.4 onward */
tree_node<N>*& current = this->current;
assert(current != NULL);
for (tree_node<N>* p = current->first_child;
p != NULL; p = p->next_sibling)
{
queue.push_front(p);
}
if (queue.empty())
{
current = NULL;
}
else
{
current = queue.back();
queue.pop_back();
}
return *this;
}
};
@@ -0,0 +1,43 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
template<class N>
size_t tree<N>::const_iterator::size(void) const
{
size_t s = 1;
for (typename tree<N>::const_sibling_iterator i(beginChildren());
i != endChildren(); ++i)
{
s += i.size();
}
return s;
}
@@ -0,0 +1,74 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/** An iterator that can be used to inspect the tree but not modify it.
*/
class const_iterator : public tree_iterator<N, const N&, const N*>
{
friend class tree;
/* allows iterator to call the protected constructor below */
friend tree<N>::iterator::operator const_iterator() const;
private:
/* this typedef is very convenient and allows Java-like code */
typedef tree_iterator<N, const N&, const N*> super;
protected:
const_iterator(tree_node<N>* current) : super(current) { }
public:
const_iterator(void) { }
const_iterator(const const_iterator& iter) : super(iter) { }
typename super::reference
operator * (void) const { return this->current->data; }
typename super::pointer
operator -> (void) const { return &(this->current->data); }
const_sibling_iterator beginChildren(void) const
{ return const_sibling_iterator(const_iterator(this->current->first_child)); }
const_sibling_iterator endChildren(void) const
{ return const_sibling_iterator(const_iterator(NULL)); }
const_iterator parent(void) const
{ return this->current->parent; }
/** Determines the size of the subtree below and including this position.
*
* @return The size of this subtree.
*/
size_t size(void) const;
};
@@ -0,0 +1,58 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/** Iterates through the graph visiting parents after children and does not allow changes.
*/
class const_postorder_iterator : public virtual const_iterator
{
friend class tree;
private:
explicit const_postorder_iterator(tree_node<N>* current) : const_iterator(current) { }
public:
const_postorder_iterator(void) { }
const_postorder_iterator(const const_iterator& iter) : const_iterator(iter) { }
const_postorder_iterator& operator++(void)
{
post_inc(this->current, this->iter_depth);
return *this;
}
const_postorder_iterator& operator--(void)
{
post_dec(this->current, this->iter_depth);
return *this;
}
};
@@ -0,0 +1,74 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/** Iterates through the graph visiting parents before children and does not allow changes.
*/
class const_preorder_iterator : public virtual const_iterator
{
friend class tree;
private:
explicit const_preorder_iterator(tree_node<N>* current) : const_iterator(current) { }
public:
const_preorder_iterator(void) { }
const_preorder_iterator(const const_iterator& iter) : const_iterator(iter) { }
const_preorder_iterator& operator++(void)
{
pre_inc(this->current, this->iter_depth);
return *this;
}
const_preorder_iterator& operator--(void)
{
pre_dec(this->current, this->iter_depth);
return *this;
}
/** Skips the children of this node and moves
* to what would normally be the next node
* had the children actually been visited. */
const_preorder_iterator& prune(void)
{
while (this->current->next_sibling == NULL)
{
this->current = this->current->parent;
this->iter_depth--;
if (this->current == NULL)
return *this;
}
this->current = this->current->next_sibling;
return *this;
}
};
@@ -0,0 +1,92 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/** Iterates through nodes that have the same parent and does not
* allow changes.
*/
class const_sibling_iterator : public virtual const_iterator
{
friend class tree;
private:
explicit const_sibling_iterator(tree_node<N>* current) : const_iterator(current) { }
public:
const_sibling_iterator(void) { }
const_sibling_iterator(const const_iterator& iter) : const_iterator(iter) { }
const_sibling_iterator& operator++(void)
{
sib_inc(this->current);
return *this;
}
const_sibling_iterator operator ++ (int)
{
const_sibling_iterator tmp(*this);
sib_inc(this->current);
return tmp;
}
const_sibling_iterator& operator--(void)
{
sib_dec(this->current);
return *this;
}
const_sibling_iterator operator -- (int)
{
const_sibling_iterator tmp(*this);
sib_dec(this->current);
return tmp;
}
const_sibling_iterator operator + (unsigned int n) const
{
const_sibling_iterator i(*this);
while (n-- > 0)
++i;
return i;
}
const_sibling_iterator operator - (unsigned int n) const
{
const_sibling_iterator i(*this);
while (n-- > 0)
--i;
return i;
}
};
@@ -0,0 +1,361 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
template<class N>
void tree<N>::iterator::clear(void)
{
/* this line necessary for g++ 3.4 onward */
tree_node<N>*& current = this->current;
assert(current != NULL);
for (sibling_iterator i(beginChildren());
i != endChildren(); )
{
i.clear();
++i;
(i - 1).destroy();
}
current->first_child = NULL;
current->last_child = NULL;
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::erase(void)
{
tree_node<N>*& current = this->current;
assert(current != NULL);
/* remove all children and grandchildren */
clear();
/* make copies because there is an ordering
problem updating the previous and next links */
tree_node<N>* old_prev = current->prev_sibling;
tree_node<N>* old_next = current->next_sibling;
if (old_prev != NULL)
old_prev->next_sibling = old_next;
if (old_next != NULL)
old_next->prev_sibling = old_prev;
if (current->parent->first_child == current)
current->parent->first_child = old_next;
if (current->parent->last_child == current)
current->parent->last_child = old_prev;
/* destroy has no parameters, so gcc complains that it
can't find the method unless this is made explicit */
super::destroy();
return iterator(old_next);
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::insert(const N& data)
{
tree_node<N>*& current = this->current;
assert(current != NULL);
tree_node<N>* p = new tree_node<N>(data);
p->parent = current->parent;
p->first_child = p->last_child = NULL;
p->prev_sibling = current->prev_sibling;
p->next_sibling = current;
if (current->prev_sibling != NULL)
current->prev_sibling->next_sibling = p;
else
current->parent->first_child = p;
current->prev_sibling = p;
return p;
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::insert(const tree<N>& t)
{
assert(this->current != NULL);
return absorb_before(new tree<N>(t));
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::insert_after(const N& data)
{
/* this line necessary for g++ 3.4 onward */
tree_node<N>*& current = this->current;
assert(current != NULL);
tree_node<N>* p = new tree_node<N>(data);
p->parent = current->parent;
p->first_child = p->last_child = NULL;
p->prev_sibling = current;
p->next_sibling = current->next_sibling;
if (current->next_sibling != NULL)
current->next_sibling->prev_sibling = p;
else
current->parent->last_child = p;
current->next_sibling = p;
return p;
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::insert_after(const tree<N>& t)
{
assert(this->current != NULL);
return absorb_after(new tree<N>(t));
}
template<class N>
void tree<N>::iterator::pop_back(void)
{
/* this line necessary for g++ 3.4 onward */
tree_node<N>*& current = this->current;
assert(current != NULL);
assert(current->last_child != NULL);
assert(current->last_child->next_sibling == NULL);
tree_node<N>* p = current->last_child;
current->last_child = p->prev_sibling;
if (p->prev_sibling != NULL)
p->prev_sibling->next_sibling = NULL;
else
current->first_child = NULL;
delete p;
}
template<class N>
void tree<N>::iterator::pop_front(void)
{
/* this line necessary for g++ 3.4 onward */
tree_node<N>*& current = this->current;
assert(current != NULL);
assert(current->first_child != NULL);
assert(current->first_child->prev_sibling == NULL);
tree_node<N>* p = current->first_child;
current->first_child = p->next_sibling;
if (p->next_sibling != NULL)
p->next_sibling->prev_sibling = NULL;
else
current->last_child = NULL;
delete p;
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::push_back(const N& data)
{
/* this line necessary for g++ 3.4 onward */
tree_node<N>*& current = this->current;
assert(current != NULL);
tree_node<N>* p = new tree_node<N>(data);
p->parent = current;
p->first_child = p->last_child = NULL;
if (current->last_child == NULL)
{
current->first_child = current->last_child = p;
p->prev_sibling = p->next_sibling = NULL;
}
else
{
p->prev_sibling = current->last_child;
p->next_sibling = NULL;
current->last_child->next_sibling = p;
current->last_child = p;
}
return iterator(p);
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::push_back(const tree<N>& t)
{
assert(this->current != NULL);
return absorb_back(new tree<N>(t));
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::push_front(const N& data)
{
/* this line necessary for g++ 3.4 onward */
tree_node<N>*& current = this->current;
assert(current != NULL);
tree_node<N>* p = new tree_node<N>(data);
p->parent = current;
p->first_child = p->last_child = NULL;
if (current->first_child == NULL)
{
current->first_child = current->last_child = p;
p->prev_sibling = p->next_sibling = NULL;
}
else
{
p->prev_sibling = NULL;
p->next_sibling = current->first_child;
current->first_child->prev_sibling = p;
current->first_child = p;
}
return iterator(p);
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::push_front(const tree<N>& t)
{
assert(this->current != NULL);
return absorb_front(new tree<N>(t));
}
template<class N>
N tree<N>::iterator::replace(const N& data)
{
N ret(this->current->data);
this->current->data = data;
return ret;
}
template<class N>
size_t tree<N>::iterator::size(void) const
{
assert(this->current != NULL);
size_t s = 1;
for (typename tree<N>::sibling_iterator i(beginChildren());
i != endChildren(); ++i)
{
s += i.size();
}
return s;
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::splice_after(tree<N>& t)
{
/* this line necessary for g++ 3.4 onward */
tree_node<N>*& current = this->current;
assert(current != NULL);
tree_node<N>* p = t.master->next_sibling;
t.master->next_sibling = t.master;
t.master->prev_sibling = t.master;
p->parent = current->parent;
p->prev_sibling = current;
p->next_sibling = current->next_sibling;
if (current->next_sibling != NULL)
current->next_sibling->prev_sibling = p;
else
current->parent->last_child = p;
current->next_sibling = p;
return p;
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::splice_back(tree<N>& t)
{
/* this line necessary for g++ 3.4 onward */
tree_node<N>*& current = this->current;
assert(current != NULL);
assert(!t.empty());
tree_node<N>* p = t.master->next_sibling;
t.master->next_sibling = t.master;
t.master->prev_sibling = t.master;
p->parent = current;
if (current->last_child == NULL)
{
current->first_child = current->last_child = p;
p->prev_sibling = p->next_sibling = NULL;
}
else
{
p->prev_sibling = current->last_child;
p->next_sibling = NULL;
current->last_child->next_sibling = p;
current->last_child = p;
}
return p;
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::splice_before(tree<N>& t)
{
/* TODO */
assert(false);
return NULL;
}
template<class N>
typename tree<N>::iterator tree<N>::iterator::splice_front(tree<N>& t)
{
/* TODO */
assert(false);
return NULL;
}
@@ -0,0 +1,251 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/** An iterator that can be used to modify the tree. Most of the methods
* provided by this class perform actions relative to the current position
* of the iterator.
*/
class iterator : public tree_iterator<N, N&, N*>
{
friend class tree;
private:
/* this typedef is very convenient and allows Java-like code */
typedef tree_iterator<N, N&, N*> super;
protected:
iterator(tree_node<N>* current) : super(current) { }
public:
/** Creates an iterator that doesn't point to anything yet. */
iterator(void) { }
/** Copy constructor */
iterator(const iterator& iter) : super(iter) { }
/** Converts an iterator to a const_iterator. This conversion
* is one-way; const_iterator does not have a corresponding
* conversion function to iterator.
*/
operator const_iterator() const
{ return const_iterator(this->current); }
typename super::reference
operator * (void) const { return this->current->data; }
typename super::pointer
operator -> (void) const { return &(this->current->data); }
/** Identical to the splice_after method except deletes the tree
* after performing the splice.
*
* @return An iterator pointing to the root of the absorbed tree.
*/
iterator absorb_after(tree<N>* t)
{
assert(t != NULL);
assert(!t->empty());
iterator i = splice_after(*t);
delete t;
return i;
}
/** Identical to the splice_back method except deletes the tree
* after performing the splice.
*
* @return An iterator pointing to the root of the absorbed tree.
*/
iterator absorb_back(tree<N>* t)
{
#if !defined(TREE_NO_ERROR_CHECKING) && defined(TREE_EXCEPTIONS)
if (t == NULL || t->empty())
{
throw typename tree<N>::null_tree_exception("in absorb_back");
}
#else
assert(t != NULL);
assert(!t->empty());
#endif
iterator i = splice_back(*t);
delete t;
return i;
}
/** Identical to the splice_before method except deletes the tree
* after performing the splice.
*
* @return An iterator pointing to the root of the absorbed tree.
*/
iterator absorb_before(tree<N>* t)
{
assert(t != NULL);
assert(!t->empty());
iterator i = splice_before(*t);
delete t;
return i;
}
/** Identical to the splice_front method except deletes the tree
* after performing the splice.
*
* @return An iterator pointing to the root of the absorbed tree.
*/
iterator absorb_front(tree<N>* t)
{
assert(t != NULL);
assert(!t->empty());
iterator i = splice_front(*t);
delete t;
return i;
}
sibling_iterator beginChildren(void) const
{ return sibling_iterator(iterator(this->current->first_child)); }
/** Removes all children and grandchildren of this node
*/
void clear(void);
sibling_iterator endChildren(void) const
{ return sibling_iterator(iterator(NULL)); }
/** Removes this node and returns an iterator pointing
* to the next node. */
iterator erase(void);
/** Inserts a new node before this node and returns an
* iterator pointing to the new node. */
iterator insert(const N& data);
iterator insert(const tree<N>& t);
/** Inserts a new node after this node and returns an
* iterator pointing to the new node. */
iterator insert_after(const N& data);
iterator insert_after(const tree<N>& t);
iterator parent(void) const
{ return this->current->parent; }
/** Removes the last child of this node.
*/
void pop_back(void);
/** Removes the first child of this node.
*/
void pop_front(void);
/** Adds a node to the end of this position's child list.
*
* @param data Data for the new node.
*
* @return An iterator pointing to the new node.
*/
iterator push_back (const N& data);
/** Adds a copy of a tree to the end of this position's child list.
*
* @param t The tree to copy.
*
* @return An iterator pointing to the root of the inserted subtree.
*/
iterator push_back (const tree<N>& t);
/** Adds a node to the beginning of this position's child list.
*
* @param data Data for the new node.
*
* @return An iterator pointing to the new node.
*/
iterator push_front(const N& data);
/** Adds a copy of a tree to the beginning of this position's child list.
*
* @param t The tree to copy.
*
* @return An iterator pointing to the root of the inserted subtree.
*/
iterator push_front(const tree<N>& t);
/** Replaces the data at this position.
*
* @param data The new data.
*
* @return The old data.
*/
N replace(const N& data);
/** Determines the size of the subtree below and including this position.
*
* @return The size of this subtree.
*/
size_t size(void) const;
/** Moves nodes from a tree (without copying) such that
* the tree becomes the next sibling of this node.
*
* @param t The tree to move. It will be empty after this method returns.
*
* @return An iterator pointing to the root of the spliced tree.
*/
iterator splice_after(tree<N>& t);
/** Moves nodes from a tree (without copying) such that the tree becomes the last child of this node.
*
* @param t The tree to move. It will be empty after this method returns.
*
* @return An iterator pointing to the root of the spliced tree.
*/
iterator splice_back(tree<N>& t);
/** Moves nodes from a tree (without copying) such that the tree becomes the previous child of this node.
*
* @param t The tree to move. It will be empty after this method returns.
*
* @return An iterator pointing to the root of the spliced tree.
*/
iterator splice_before(tree<N>& t);
/** Moves nodes from a tree (without copying) such that the tree becomes the first child of this node.
*
* @param t The tree to move. It will be empty after this method returns.
*
* @return An iterator pointing to the root of the spliced tree.
*/
iterator splice_front(tree<N>& t);
};
@@ -0,0 +1,58 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/** Iterates through the graph visiting parents after children and allows changes.
*/
class postorder_iterator : public virtual iterator
{
friend class tree;
private:
explicit postorder_iterator(tree_node<N>* current) : iterator(current) { }
public:
postorder_iterator(void) { }
postorder_iterator(const iterator& iter) : iterator(iter) { }
postorder_iterator& operator++(void)
{
post_inc(this->current, this->iter_depth);
return *this;
}
postorder_iterator& operator--(void)
{
post_dec(this->current, this->iter_depth);
return *this;
}
};
@@ -0,0 +1,58 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/** Iterates through the graph visiting parents before children and allows changes.
*/
class preorder_iterator : public virtual iterator
{
friend class tree;
private:
explicit preorder_iterator(tree_node<N>* current) : iterator(current) { }
public:
preorder_iterator(void) { }
preorder_iterator(const iterator& iter) : iterator(iter) { }
preorder_iterator& operator++(void)
{
pre_inc(this->current, this->iter_depth);
return *this;
}
preorder_iterator& operator--(void)
{
pre_dec(this->current, this->iter_depth);
return *this;
}
};
@@ -0,0 +1,108 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/** Iterates through nodes that have the same parent and allows changes.
*/
class sibling_iterator : public virtual iterator
{
friend class tree;
private:
explicit sibling_iterator(tree_node<N>* current) : iterator(current) { }
public:
sibling_iterator(void) { }
sibling_iterator(const iterator& iter) : iterator(iter) { }
sibling_iterator& operator ++ (void)
{
sib_inc(this->current);
return *this;
}
sibling_iterator operator ++ (int)
{
sibling_iterator tmp(*this);
sib_inc(this->current);
return tmp;
}
sibling_iterator& operator -- (void)
{
sib_dec(this->current);
return *this;
}
sibling_iterator operator -- (int)
{
sibling_iterator tmp(*this);
sib_dec(this->current);
return tmp;
}
sibling_iterator operator + (unsigned int n) const
{
sibling_iterator i(*this);
while (n-- > 0)
++i;
return i;
}
sibling_iterator& operator += (unsigned int n)
{
while (n-- > 0)
sib_inc(this->current);
return *this;
}
sibling_iterator operator - (unsigned int n) const
{
sibling_iterator i(*this);
while (n-- > 0)
--i;
return i;
}
sibling_iterator& operator -= (unsigned int n)
{
while (n-- > 0)
sib_dec(this->current);
return *this;
}
};
@@ -0,0 +1,156 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
template <class N>
template <class InputIterator>
tree<N>::tree(InputIterator first, InputIterator last, unsigned int n)
{
assert(n != 0);
createMaster();
if (first == last)
return;
setRoot(*first);
/* don't directly initialize i to first + 1 because not all STL
iterators support addition */
InputIterator i(first);
if (++i == last)
return;
/* Make a list of leaves. Initially the list contains only the
root. Pick a leaf and add items to it until it is full.
Added items become new leaves. Continue until there
are no more items */
std::list<typename tree<N>::iterator> leaves;
leaves.push_back(getRoot());
for (;;)
{
typename tree<N>::iterator leaf(leaves.front());
for (unsigned int k = 0; k < n; ++k)
{
leaves.push_back(leaf.push_back(*i));
if (++i == last)
return;
}
leaves.pop_front();
}
}
template <class N>
void tree<N>::copy_subtree(tree<N>::const_iterator subtree)
{
/* Copying replaces this tree. */
clear();
/* Original is empty, so leave it empty. */
if (subtree == NULL)
return;
/* Copy the root data. */
sibling_iterator root(setRoot(*subtree));
/* Recursively copy the children. */
for (const_sibling_iterator i(subtree.beginChildren());
i != subtree.endChildren(); ++i)
root.absorb_back(new tree<N>(i));
}
template <class N>
void tree<N>::clear(void)
{
if (empty())
return;
/* delete all nodes bottom-up */
for (postorder_iterator i(beginPost()); i != endPost(); )
{
postorder_iterator tmp(i);
++i;
tmp.destroy();
}
/* Preserve master invariant. */
master->first_child = master->last_child = NULL;
master->prev_sibling = master->next_sibling = master;
/* Leave the master for the destructor. */
}
template <class N>
size_t tree<N>::height(void) const
{
size_t h = 0;
for (const_preorder_iterator i(beginPre()); i != endPre(); ++i)
{
if (static_cast<size_t>(i.depth() + 1) > h)
h = i.depth() + 1;
}
return h;
}
template <class N>
size_t tree<N>::height_leftmost(void) const
{
size_t h = 0;
tree_node<N>* p = master->next_sibling;
if (p != master)
{
do {
++h;
p = p->first_child;
} while (p != NULL);
}
return h;
}
template<class N>
size_t tree<N>::size(void) const
{
size_t s = 0;
for (const_preorder_iterator i(beginPre()); i != endPre(); ++i)
++s;
return s;
}
@@ -0,0 +1,871 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TREE_H
#define TREE_H
#include <cassert>
#include <list>
#include <stdexcept>
#include <string>
/* master invariant checks are sprinkled throughout to check
for catastrophic errors */
#if defined(TREE_NO_ERROR_CHECKING)
#define TREE_MASTER_INVARIANT
#else
#if defined(TREE_EXCEPTIONS)
#define TREE_MASTER_INVARIANT check_master_invariant()
#else
#define TREE_MASTER_INVARIANT assert(master != NULL); \
assert(master->next_sibling != NULL)
#endif
#endif
/* experimental */
// #define TREE_POINTER_SPECIALIZATION
namespace taj /* my initials */
{
/** Provides a generic n-ary acyclic tree container that behaves similarly
* to and is mostly compatible with other standard C++ templates. Various
* iterators are provided, with pruning options. Iterators are also used
* to represent subtrees.
*
* In the spirit of the standard template library, the BSD license makes
* my tree class available for all to use. I would appreciate receiving
* patches to fix any bugs you may discover or suggestions on how to
* improve the template.
*
* The STL list template was my initial inspiration for how to implement
* the tree class, but I determined there was little benefit from
* starting with that code. This template class does not use any code
* from the STL classes, but is designed to be compatible and have similar
* method names for consistency. I intend for this class to be very
* efficient in terms of size and speed, just like the STL classes.
*
* The std::list template uses many supporting classes that are found in
* the std namespace or public in the std::list namespace. This tree
* template does not pollute the global namespace as much by keeping all
* the supporting classes inside the main class. If the user includes
* the taj namespace, the only name that gets sucked into the enclosing
* namespace is tree. I feel this is a better design. The following were
* some motivating factors:
*
* 1) The tree_node class should be invisible to the user. The user wants to
* think of the N in tree<N> as the node type of the tree. In the standard
* list template, struct _List_node is similarly irrelevant to the user
* but unnecessarily appears in the std namespace.
*
* 2) The base template for the iterators should be a true class instead of a
* wide-open struct. Furthermore, it should not be accessible to the user.
* A consequence of nesting the iterators inside the tree class is needing
* to make the tree their friend, but this is an example of how to use
* friends correctly.
*
* There is a lot of code here, so I have divided it into several header
* files and code files. The only header the user needs to include is tree.h.
*
* tree.h - the main header file for the tree class
* tree_node.h - class that represents tree nodes
* tree_iterator.h - base class for ALL iterators
* iterator.h - base class for ONLY non-const iterators
* const_iterator.h - base class for ONLY const_iterators
* (const_)preorder_iterator.h - iterators for preorder traversal
* (const_)postorder_iterator.h - iterators for postorder traversal
* (const_)bfs_iterator.h - iterators for breadth-first traversal
* (const_)sibling_iterator.h - iterators for a single tree level
*
* There is no "in-order" traversal because the tree is not necessarily
* binary. There are also .cc files which get included by this file, because
* all the code for the template needs to be in tree.h.
*
* Note concerning GCC 3.4: Template code checks are much stricter in 3.4.
* It is possible to have a template that compiles with GCC 3.3 but that does
* not compile with 3.4. The following GCC "bug" reports explain the
* workarounds, which have been incorporated into this template class.
*
* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15552
* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17649
*
* The same issue has found its way into the C++ FAQ
*
* http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12
* http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13
*
* A final note: C++ template code is weird and classes as complicated as
* this one will give your compiler good exercise. I have tested this
* class with the Debian releases of GCC 3.3.5, GCC 3.4.4, GCC 4.0.3 and
* I expect to use it with later versions. I have no idea if it works
* under other C++ compilers. If there are changes that will allow it to
* work under more compilers while still allowing it to work under GCC,
* then you are encouraged to suggest them.
*
* @author Troy A. Johnson
*/
template <class N>
class tree
{
private:
#include "tree_node.h"
#include "tree_iterator.h"
/** The real root of the tree as opposed to the first node inserted by
* the user. Also used as the end for preorder and postorder iterators
* since they finish by "falling off" the root of the tree. (The
* breadth-first iterator uses NULL for its end because it falls off
* the leaves.) As far as the user is concerned, the first node is
* master->next_sibling. This corresponds to the _M_node in
* _List_alloc_base for the standard list template.
*/
tree_node<N>* master;
public:
/* avoid annoying forward reference problems */
class iterator;
class const_iterator;
class sibling_iterator;
class const_sibling_iterator;
class preorder_iterator;
class const_preorder_iterator;
class postorder_iterator;
class const_postorder_iterator;
class bfs_iterator;
class const_bfs_iterator;
#include "iterator.h"
#include "const_iterator.h"
#include "sibling_iterator.h"
#include "const_sibling_iterator.h"
#include "preorder_iterator.h"
#include "const_preorder_iterator.h"
#include "postorder_iterator.h"
#include "const_postorder_iterator.h"
#include "bfs_iterator.h"
#include "const_bfs_iterator.h"
/* no dfs_iterator - use preorder_iterator instead */
/** Thrown if tree exceptions are turned on and a NULL is encountered
* in an incorrect place. */
class null_tree_exception : public std::runtime_error
{
public:
null_tree_exception(const std::string& s)
: std::runtime_error("null_tree_exception " + s) { }
};
private:
#if !defined(TREE_NO_ERROR_CHECKING) && defined(TREE_EXCEPTIONS)
void check_master_invariant(void)
{
if (master == NULL)
throw new null_tree_exception("tree master is null");
if (master->next_sibling == NULL)
throw new null_tree_exception("tree master->next_sibling is null");
}
#endif
/** Initializes the master node. Every tree constructor needs to
* do this so it's a separate method.
*/
void createMaster(void)
{
master = new tree_node<N>;
master->parent = NULL;
master->first_child = master->last_child = NULL;
master->prev_sibling = master->next_sibling = master;
}
/** Replaces this tree with copies of all nodes below (and including)
* the node pointed to by subtree. Used by multiple constructors.
*
* @param subtree Location from which to begin copying.
*/
void copy_subtree(const_iterator subtree);
/** Determines the leftmost child of this tree.
* Used as a starting point for postorder traversals.
*
* @return A pointer to the leftmost node or master if
* the tree is empty.
*/
tree_node<N>* leftmostChild(void) const
{
TREE_MASTER_INVARIANT;
tree_node<N>* p = master->next_sibling;
while (p->first_child != NULL)
p = p->first_child;
return p;
}
public:
/** Provides access to an iterator suitable for postorder traversal,
* initially pointing to the leftmost child of this tree.
*
* @return An iterator for postorder traversal.
*/
postorder_iterator beginPost(void)
{ return postorder_iterator(leftmostChild()); }
/** Provides access to an iterator suitable for postorder traversal,
* initially pointing to the leftmost child of this tree.
*
* @return A constant iterator for postorder traversal.
*/
const_postorder_iterator beginPost(void) const
{ return const_postorder_iterator(leftmostChild()); }
/** Provides access to an iterator representing the end of a
* postorder traversal.
*
* @return The end of a postorder traversal.
*/
postorder_iterator endPost(void)
{ return postorder_iterator(master); }
/** Provides access to an iterator representing the end of a
* constant postorder traversal.
*
* @return The end of a constant postorder traversal.
*/
const_postorder_iterator endPost(void) const
{ return const_postorder_iterator(master); }
/** Provides access to an iterator suitable for preorder traversal,
* initially pointing to the root of this tree.
*
* @return An iterator for preorder traversal.
*/
preorder_iterator beginPre(void)
{ return preorder_iterator(master->next_sibling); }
/** Provides access to an iterator suitable for preorder traversal,
* initially pointing to the root of this tree.
*
* @return A constant iterator for preorder traversal.
*/
const_preorder_iterator beginPre(void) const
{ return const_preorder_iterator(master->next_sibling); }
/** Provides access to an iterator representing the end of a
* preorder traversal.
*
* @return The end of a preorder traversal.
*/
preorder_iterator endPre(void)
{ return preorder_iterator(master); }
/** Provides access to an iterator representing the end of a
* constant preorder traversal.
*
* @return The end of a constant preorder traversal.
*/
const_preorder_iterator endPre(void) const
{ return const_preorder_iterator(master); }
/** Provides access to an iterator suitable for breadth-first traversal,
* initially pointing to the root of this tree.
*
* @return An iterator for breadth-first traversal.
*/
bfs_iterator beginBfs(void)
{ return bfs_iterator(master->next_sibling); }
/** Provides access to an iterator suitable for breadth-first traversal,
* initially pointing to the root of this tree.
*
* @return A constant iterator for breadth-first traversal.
*/
const_bfs_iterator beginBfs(void) const
{ return const_bfs_iterator(master->next_sibling); }
/** Provides access to an iterator representing the end of a
* breadth-first traversal.
*
* @return The end of a breadth-first traversal.
*/
bfs_iterator endBfs(void)
{ return bfs_iterator(NULL); }
/** Provides access to an iterator representing the end of a
* constant breadth-first traversal.
*
* @return The end of a constant breadth-first traversal.
*/
const_bfs_iterator endBfs(void) const
{ return const_bfs_iterator(NULL); }
/** Creates an empty tree. A root node can be created with setRoot later.
*/
tree(void)
{
createMaster();
}
/** Creates a single-node tree.
*
* @param root_data The data to use for the root of the tree.
*/
explicit tree(const N& root_data)
{
createMaster();
setRoot(root_data);
}
/** Copies an existing subtree.
*
* @param subtree The root of the original subtree
* from which to make the copy.
*/
explicit tree(const_iterator subtree)
{
createMaster();
copy_subtree(subtree);
}
/** Copies an existing tree.
*
* @param orig The original tree from which to make the copy.
*/
tree(const tree<N>& orig)
{
createMaster();
copy_subtree(orig.getRoot());
}
/** Creates a tree using copies of items of another container.
* The range copied is [first, last).
*
* @param first First item to put in the tree.
* @param last The item after the final item to put in the tree.
* @param n Creates a n-ary tree. Must be greater than zero.
*/
template <class InputIterator>
tree(InputIterator first, InputIterator last, unsigned int n);
/** Copies an existing tree.
*
* @param orig The original tree from which to make the copy.
*
* @return A reference to this tree to be used in chained assignments.
*/
const tree<N>& operator = (const tree<N>& orig)
{
copy_subtree(orig.getRoot());
return *this;
}
/** Empties and destroys the tree.
*/
virtual ~tree(void)
{
TREE_MASTER_INVARIANT;
clear();
delete master;
}
/** Empties the tree. All nodes are deleted. If the node type
* is a pointer, it is the user's responsibility to delete
* the data to which they point before clearing the tree.
*/
void clear(void);
/** Checks if the tree is empty.
*
* @return true if the tree is empty, false otherwise.
*/
bool empty(void) const
{
TREE_MASTER_INVARIANT;
return (master->next_sibling == master);
}
/** Provides access to the root of the tree.
*
* @return An iterator pointing at the root node.
*/
iterator getRoot(void)
{
TREE_MASTER_INVARIANT;
return iterator(master->next_sibling);
}
/** Provides access to the root of an unmodifiable tree.
*
* @return An iterator pointing at the root node.
*/
const_iterator getRoot(void) const
{
TREE_MASTER_INVARIANT;
return const_iterator(master->next_sibling);
}
/** Determines the height of the tree. This operation is
* general and is linear in the size of the tree, not
* the height.
*
* @return The height of the tree.
*/
size_t height(void) const;
/** Determines the height of the tree using
* the leftmost grandchild of the root. This operation is
* guaranteed to be linear in the height of the tree, but
* may not be the true height for some trees.
*
* @return The height of the leftmost grandchild of the root.
*/
size_t height_leftmost(void) const;
/** Sets the data of the root node, or creates one if it was not set
* when the tree was created.
*
* @return An iterator pointing to the root node.
*/
iterator setRoot(const N& root_data)
{
if (empty())
{
tree_node<N>* root = new tree_node<N>(root_data);
root->parent = NULL;
root->first_child = root->last_child = NULL;
root->next_sibling = root->prev_sibling = master;
master->prev_sibling = master->next_sibling = root;
}
else
*getRoot() = root_data;
return getRoot();
}
/** Determines the number of nodes in the tree.
* Unfortunately this requires a full tree traversal.
* This could be expensive, but it's far simpler than
* making iterators aware of what tree they are modifying
* and updating the current size of that tree. For simple
* insertion and deletion that might not be difficult,
* but for more complex operations it very well might be.
* Doing it this way makes size a known expensive operation
* instead of adding overhead to a large number of other calls.
* If the user knows how many nodes they have added or deleted
* since their last size call, then they can compute the current
* size without calling size. It should be noted that the
* standard library list template works the same way.
*
* @return The number of nodes in the tree.
*/
size_t size(void) const;
};
#include "tree_iterator.cc"
#include "iterator.cc"
#include "const_iterator.cc"
/* keep this include last */
#include "tree.cc"
/* TODO - Pointer specialization
This is experimental and may not work at all.
*/
#if defined(TREE_POINTER_SPECIALIZATION)
template class tree<void*>;
template <class N>
class tree<N*> : private tree<void*>
{
public:
/* do not prefix these forward declarations with tree<N*>:: */
class iterator;
class const_iterator;
class sibling_iterator;
class const_sibling_iterator;
class preorder_iterator;
class const_preorder_iterator;
class postorder_iterator;
class const_postorder_iterator;
class bfs_iterator;
class const_bfs_iterator;
class iterator : private virtual tree<void*>::iterator
{
friend class tree<N*>;
typedef class tree<N*>::iterator self;
typedef class tree<void*>::iterator super;
protected:
iterator(const super& iter) : super(iter) { }
public:
iterator(void) { }
iterator(const self& iter) : super(iter) { }
// operator const_iterator()
// { return static_cast<typename tree<void*>::const_iterator>(*this); }
bool operator == (const self& iter) const
{ return super(*this) == super(iter); }
bool operator != (const self& iter) const
{ return super(*this) != super(iter); }
using super::clear;
using super::depth;
typename tree<N*>::sibling_iterator beginChildren(void) const
{ return self(super::beginChildren()); }
typename tree<N*>::sibling_iterator endChildren(void) const
{ return self(super::endChildren()); }
N*&
operator * (void) const { return reinterpret_cast<N*&>(this->current->data); }
N**
operator -> (void) const { return reinterpret_cast<N**>(&(this->current->data)); }
self absorb_back(tree<N*>* t)
{ return super::absorb_back(t); }
self push_back(N* data)
{ return super::push_back(data); }
N* replace(N* data)
{ return reinterpret_cast<N*>(super::replace(data)); }
};
class const_iterator : private virtual tree<void*>::const_iterator
{
friend class tree<N*>;
typedef class tree<N*>::const_iterator self;
typedef class tree<void*>::const_iterator super;
protected:
const_iterator(const super& iter) : super(iter) { }
public:
const_iterator(void) { }
const_iterator(const self& iter) : super(iter) { }
bool operator == (const self& iter) const
{ return super(*this) == super(iter); }
bool operator != (const self& iter) const
{ return super(*this) != super(iter); }
using super::depth;
N* const &
operator * (void) const { return reinterpret_cast<N* const &>(this->current->data); }
N* const *
operator -> (void) const { return reinterpret_cast<N* const *>(&(this->current->data)); }
};
class sibling_iterator : public tree<N*>::iterator, private tree<void*>::sibling_iterator
{
friend class tree<N*>;
private:
sibling_iterator(const tree<void*>::sibling_iterator& iter) : tree<N*>::iterator(iter) { }
public:
sibling_iterator(void) { }
sibling_iterator(const tree<N*>::iterator& iter) : tree<N*>::iterator(iter) { }
using tree<N*>::iterator::operator *;
typename tree<N*>::sibling_iterator& operator ++ (void)
{ ++static_cast<tree<void*>::sibling_iterator>(*this); return *this; }
};
#if 0
class const_sibling_iterator : public const_iterator
{
friend class tree<N*>;
private:
// const_sibling_iterator(const tree<void*>::const_sibling_iterator& iter) : const_iterator(iter) { }
public:
const_sibling_iterator(const const_iterator& iter) : const_iterator(iter) { }
};
#endif
class preorder_iterator : public tree<N*>::iterator, private tree<void*>::preorder_iterator
{
friend class tree<N*>;
private:
preorder_iterator(const tree<void*>::preorder_iterator& iter) : tree<N*>::iterator(iter) { }
public:
preorder_iterator(const tree<N*>::iterator& iter) : tree<N*>::iterator(iter) { }
using tree<N*>::iterator::operator ==;
using tree<N*>::iterator::operator !=;
using tree<N*>::iterator::operator *;
typename tree<N*>::preorder_iterator& operator ++ (void)
{ ++static_cast<tree<void*>::preorder_iterator>(*this); return *this; }
using tree<N*>::iterator::replace;
};
class const_preorder_iterator : public tree<N*>::const_iterator, private tree<void*>::const_preorder_iterator
{
friend class tree<N*>;
private:
const_preorder_iterator(const tree<void*>::const_preorder_iterator& iter) : tree<void*>::const_preorder_iterator(iter) { }
public:
const_preorder_iterator(const tree<N*>::const_iterator& iter) : tree<N*>::const_iterator(iter) { }
using tree<N*>::const_iterator::operator *;
typename tree<N*>::const_preorder_iterator& operator ++ (void)
{ ++static_cast<tree<void*>::const_preorder_iterator>(*this); return *this; }
};
#if 0
class postorder_iterator : private tree<void*>::postorder_iterator
{
friend class tree<N*>;
private:
// postorder_iterator(const tree<void*>::postorder_iterator& iter) : iterator(iter) { }
public:
postorder_iterator(const iterator& iter) : tree<void*>::postorder_iterator(iter) { }
};
class const_postorder_iterator : private tree<void*>::const_postorder_iterator
{
friend class tree<N*>;
private:
// const_postorder_iterator(const tree<void*>::const_postorder_iterator& iter) : const_iterator(iter) { }
public:
const_postorder_iterator(const const_iterator& iter) : tree<void*>::const_postorder_iterator(iter) { }
};
class bfs_iterator : private tree<void*>::bfs_iterator
{
friend class tree<N*>;
private:
// bfs_iterator(const tree<void*>::bfs_iterator& iter) : iterator(iter) { }
public:
bfs_iterator(const iterator& iter) : tree<void*>::bfs_iterator(iter) { }
};
class const_bfs_iterator : private tree<void*>::const_bfs_iterator
{
friend class tree<N*>;
private:
// const_bfs_iterator(const tree<void*>::const_bfs_iterator& iter) : const_iterator(iter) { }
public:
const_bfs_iterator(const const_iterator& iter) : tree<void*>::const_bfs_iterator(iter) { }
};
#endif
tree(void) : tree<void*>::tree()
{
}
/** Creates a single-node tree.
*
* @param root_data The data to use for the root of the tree.
*/
explicit tree(N* root_data) : tree<void*>::tree(root_data)
{
}
explicit tree(const_iterator subtree) : tree<void*>::tree(subtree)
{
}
tree(const tree<N*>& orig) : tree<void*>::tree(orig)
{
}
preorder_iterator beginPre(void)
{ return tree<void*>::beginPre(); }
const_preorder_iterator beginPre(void) const
{ return tree<void*>::beginPre(); }
preorder_iterator endPre(void)
{ return tree<void*>::endPre(); }
const_preorder_iterator endPre(void) const
{ return tree<void*>::endPre(); }
iterator getRoot(void)
{ return tree<void*>::getRoot(); }
const_iterator getRoot(void) const
{ return tree<void*>::getRoot(); }
iterator setRoot(N* root_data)
{ return tree<void*>::setRoot(root_data); }
};
#if 0
template class tree<void*>;
template class tree<void*>::tree_node<void*>;
template <class N>
class tree<N*> : public tree<void*>
{
public:
// class const_iterator;
private:
template <class T>
class tree_node<T*> : public tree_node<void*>
{
public:
tree_node(void) : tree_node<void*>() { }
tree_node(T* data) : tree_node<void*>(data) { }
};
/*
template <class T, class R, class P>
class tree_iterator<T*, R*, P*> : public tree_iterator<void*, void*&, void**>
{
};
*/
public:
tree(void) : tree<void*>()
{
std::cout << "specialized tree default constructor" << std::endl;
}
explicit tree(N* root_data) : tree<void*>(root_data)
{
}
};
/*
template<class N>
class tree<N*>::iterator : public tree<N>::template tree_iterator<N*, N&, N*>
{
};
*/
template <class N>
class tree<N*>::const_iterator : public tree<void*>::iterator
{
private:
/* this typedef is very convenient and allows Java-like code */
typedef typename tree<N*>::template tree_iterator<N*, const N*&, const N**> super;
public:
typename super::reference
operator * (void) const { return this->current->data; }
};
//template <class N*>
//typename tree<N*>::template tree_iterator<N*, const N*&, const N**>::reference
//tree<N*>::template const_iterator::operator * (void) const
//{ return this->current->data; }
#endif
#endif
} /* namespace taj */
#undef TREE_MASTER_INVARIANT
#endif
@@ -0,0 +1,136 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
template<class N>
template<class T, class R, class P>
void tree<N>::tree_iterator<T, R, P>::post_inc(tree_node<N>*& current, long& depth)
{
assert(current != NULL);
if (current->next_sibling == NULL)
{
current = current->parent;
depth--;
}
else
{
current = current->next_sibling;
while (current->first_child != NULL)
{
current = current->first_child;
depth++;
}
}
}
template<class N>
template<class T, class R, class P>
void tree<N>::tree_iterator<T, R, P>::post_dec(tree_node<N>*& current, long& depth)
{
assert(current != NULL);
if(current->last_child == NULL)
{
while (current->prev_sibling == NULL)
{
current = current->parent;
depth--;
}
current = current->prev_sibling;
}
else
{
current = current->last_child;
depth++;
}
}
template<class N>
template<class T, class R, class P>
void tree<N>::tree_iterator<T, R, P>::pre_inc(tree_node<N>*& current, long& depth)
{
assert(current != NULL);
if (current->first_child != NULL)
{
current = current->first_child;
depth++;
}
else
{
while (current->next_sibling == NULL)
{
current = current->parent;
depth--;
if (current == NULL)
return;
}
current = current->next_sibling;
}
}
template<class N>
template<class T, class R, class P>
void tree<N>::tree_iterator<T, R, P>::pre_dec(tree_node<N>*& current, long& depth)
{
assert(current != NULL);
if (current->prev_sibling)
{
current = current->prev_sibling;
while (current->last_child != NULL)
{
current = current->last_child;
depth++;
}
}
else
{
current = current->parent;
depth--;
}
}
template<class N>
template<class T, class R, class P>
inline void tree<N>::tree_iterator<T, R, P>::sib_inc(tree_node<N>*& current)
{
if (current != NULL)
current = current->next_sibling;
}
template<class N>
template<class T, class R, class P>
inline void tree<N>::tree_iterator<T, R, P>::sib_dec(tree_node<N>*& current)
{
if (current != NULL)
current = current->prev_sibling;
}
@@ -0,0 +1,110 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/** The base template for all iterators.
*/
template <class T, class R, class P>
class tree_iterator
{
friend class tree;
protected:
/* The node pointed to by this iterator. */
tree_node<N>* current;
/* This is the depth of an iterator relative to its starting position.
The starting depth is 0, the depth of the parent is -1, the depth
of any child is 1, the depth of any grandchild is 2, etc. */
long iter_depth;
/** Allows derived classes to create an iterator
* from a pointer to a node. This constructor
* is not explicit because the tree_iterator class
* contains the == and != operators, which are used
* throughout the template to compare iterators
* to NULL. The tree_iterator class is not visible
* to the user, so this implicit constructor is
* entirely for my convenience when coding the template.
*
* @param current Position for the new iterator
*/
tree_iterator(tree_node<N>* current) : current(current), iter_depth(0L) { }
/** Destroys the node pointed to by this iterator.
*/
void destroy(void)
{
delete current;
current = NULL;
iter_depth = 0L;
}
/* increment and decrement methods used by both the iterator
and the const_iterator versions of various iterators */
static inline void post_inc(tree_node<N>*& current, long& depth);
static inline void post_dec(tree_node<N>*& current, long& depth);
static inline void pre_inc(tree_node<N>*& current, long& depth);
static inline void pre_dec(tree_node<N>*& current, long& depth);
static inline void sib_inc(tree_node<N>*& current);
static inline void sib_dec(tree_node<N>*& current);
public:
/* The following typedefs are required for compatibility
* with standard containers. */
typedef std::bidirectional_iterator_tag iterator_category;
typedef T value_type;
typedef R reference;
typedef P pointer;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
tree_iterator(void) : current(NULL), iter_depth(0L) { }
tree_iterator(const tree_iterator& iter)
: current(iter.current), iter_depth(iter.iter_depth) { }
/* note that depth is not relevant when comparing iterators */
bool operator == (const tree_iterator& iter) const
{ return this->current == iter.current; }
bool operator != (const tree_iterator& iter) const
{ return this->current != iter.current; }
long depth(void) const { return iter_depth; }
bool leaf(void) const { return this->first_child == NULL; }
};
@@ -0,0 +1,49 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/** Provides a tree node used internally by the tree template. Overhead added
* to the user's node type is only five pointers, so 20 additional bytes on a
* 32-bit machine.
*/
template <class T>
class tree_node
{
public:
T data;
tree_node *parent;
tree_node *first_child, *last_child;
tree_node *prev_sibling, *next_sibling;
tree_node(void) { }
tree_node(const T& data) : data(data) { }
};
@@ -0,0 +1,146 @@
/*
Copyright (c) 2003-2006, Troy Aaron Johnson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Troy Aaron Johnson nor the names of any
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <algorithm>
#include <cassert>
#include <iostream>
#include <list>
#include <string>
#include "tree.h"
using namespace taj;
bool pruning_predicate(const tree<std::string>::iterator& node)
{
return (*node == "B");
}
template <class TreeType>
void print(const tree<TreeType>& t)
{
std::cout << "preorder traversal: " << std::endl;
for (typename tree<TreeType>::const_preorder_iterator i = t.beginPre(); i != t.endPre(); ++i)
{
std::cout << *i << std::endl;
}
std::cout << std::endl;
std::cout << "postorder traversal: " << std::endl;
for (typename tree<TreeType>::const_postorder_iterator i = t.beginPost(); i != t.endPost(); ++i)
{
std::cout << *i << std::endl;
}
std::cout << std::endl;
std::cout << "bfs traversal: " << std::endl;
for (typename tree<TreeType>::const_bfs_iterator i = t.beginBfs(); i != i.endBfs(); ++i)
{
std::cout << *i << std::endl;
}
std::cout << std::endl;
}
void pointer_specialization_test(void)
{
tree<int*> pint_tree;
int x = 1, y = 2, z = 3;
tree<int*>::iterator i(pint_tree.setRoot(&x));
i.push_back(&y);
i.push_back(&z);
std::cout << "int* tree root is " << **i << std::endl;
tree<int*>::sibling_iterator si(i.beginChildren());
tree<char*> t1;
tree<long*> t2;
tree<float*> t3;
tree<double*> t4;
tree<std::string*> t5;
tree<unsigned char*> t6;
tree<unsigned long*> t7;
}
int main(int argc, char* argv[])
{
tree<std::string> t;
assert(t.empty());
assert(t.size() == 0);
tree<std::string>::sibling_iterator i(t.setRoot("root"));
assert(!t.empty());
assert(t.size() == 1);
assert(*i == "root");
*i = "new root";
assert(*i == "new root");
tree<std::string>::sibling_iterator j(i.push_back("left"));
assert(t.size() == 2);
tree<std::string>::sibling_iterator k(i.push_back("right"));
assert(t.size() == 3);
assert(*j == "left");
assert(*k == "right");
j.push_back("A");
j.push_back("B");
k.push_back("C");
k.push_back("D");
assert(find(t.beginPre(), t.endPre(), "C") != t.endPre());
assert(find(t.beginPre(), t.endPre(), "Z") == t.endPre());
std::cout << "tree height is " << t.height() << std::endl;
print(t);
tree<std::string> copy_of_t(t);
print(copy_of_t);
std::list<int> int_list;
for (int i = 1; i < 20; ++i)
int_list.push_back(i);
tree<int> int_tree(int_list.begin(), int_list.end(), 2);
print(int_tree);
pointer_specialization_test();
}