1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
/*
* TreeLib
* A library for manipulating phylogenetic trees.
* Copyright (C) 2001 Roderic D. M. Page <r.page@bio.gla.ac.uk>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// $Id: nodeiterator.h,v 1.5 2005/03/29 16:48:52 rdmp1c Exp $
/**
* @file nodeiterator.h
*
* Iterate over nodes in a tree
*
*/
/*
29 March 2005
Spent a day trying to get TreeView X to work with gcc 3.4.1 on Mandrake 10.1.
Even if it compiled, the phylogram display would cause a segmentation fault.
Eventualy tracked it down to the PreorderIterator class. Essentially, in a
templated class the inherited members need to be explicity identified, e.g.
by something like B<T>::f. Hence, in PreorderIterator I can't refer to cur
but PreorderIterator<N>::cur works. Initially when trying to get it to build I
simply duplicated the members, but this caused TreeView X to crash.
For more on this "feature" see http://lists.debian.org/debian-gcc/2004/05/msg00435.html
*/
#ifndef NODEITERATORH
#define NODEITERATORH
#ifdef __BORLANDC__
// Undefine __MINMAX_DEFINED so that min and max are correctly defined
#ifdef __MINMAX_DEFINED
#undef __MINMAX_DEFINED
#endif
// Ignore "Cannot create precompiled header: code in header" message
// generated when compiling string.cc
#pragma warn -pch
#endif
#include <vector>
#include <stack>
/**
* @class NodeIterator
* Iterator class that visits nodes in a tree in post order. Uses a stack to keep
* track of place in tree. By making this a template class we can apply it to
* any descendant of the class Node.
*
*/
template <class N> class NodeIterator
{
public:
/**
* Constructor takes the root of the tree as a parameter.
* @param r the root of the tree
*/
NodeIterator (N *r) { root = r; };
virtual ~NodeIterator () {};
/**
* Initialises the iterator and returns the first node.
* @return The first node of the tree
*/
virtual N *begin ();
/**
* Moves to the next node in the tree.
* @return The next node in the tree, or NULL if all nodes have been visited.
*/
virtual N *next ();
protected:
N *root;
N *cur;
std::stack < N *, std::vector<N *> > stk;
};
template <class N> class PreorderIterator : public NodeIterator<N>
{
public:
PreorderIterator (N *r) : NodeIterator<N> (r) {};
virtual ~PreorderIterator () {};
virtual N *begin ();
virtual N *next ();
};
template <class N> N *NodeIterator<N>::begin ()
{
cur = root;
while (cur->GetChild())
{
stk.push (cur);
cur = (N *)(cur->GetChild());
}
return cur;
}
template <class N> N *NodeIterator<N>::next ()
{
if (stk.empty())
cur = NULL;
else
{
if (cur->GetSibling())
{
N *p = (N *)(cur->GetSibling());
while (p->GetChild())
{
stk.push (p);
p = (N *)(p->GetChild());
}
cur = p;
}
else
{
cur = stk.top();
stk.pop();
}
}
return cur;
}
template <class N> N *PreorderIterator<N>::begin ()
{
PreorderIterator<N>::cur = PreorderIterator<N>::root;
return PreorderIterator<N>::cur;
}
template <class N> N *PreorderIterator<N>::next ()
{
if (PreorderIterator<N>::cur->GetChild())
{
PreorderIterator<N>::stk.push (PreorderIterator<N>::cur);
N *p = (N *)(PreorderIterator<N>::cur->GetChild());
PreorderIterator<N>::cur = p;
}
else
{
while (!PreorderIterator<N>::stk.empty() && (PreorderIterator<N>::cur->GetSibling() == NULL))
{
PreorderIterator<N>::cur = PreorderIterator<N>::stk.top();
PreorderIterator<N>::stk.pop();
}
if (PreorderIterator<N>::stk.empty())
PreorderIterator<N>::cur = NULL;
else
{
N *p = (N *)(PreorderIterator<N>::cur->GetSibling());
PreorderIterator<N>::cur = p;
}
}
return PreorderIterator<N>::cur;
}
#if __BORLANDC__
// Redefine __MINMAX_DEFINED so Windows header files compile
#ifndef __MINMAX_DEFINED
#define __MINMAX_DEFINED
#endif
#endif
#endif
|