假设您有一个通用的k-ary树like this one或this one
在此重复后者:
template <typename T>
struct TreeNode
{
T* DATA ; // data of type T to be stored at this TreeNode
vector< TreeNode<T>* > children ;
void insert( T* newData ) ;
// runs f on this and all children of this
void preorder( function<void (T*)> f )
{
f( this->DATA ) ; // exec f on this
for( int i = 0 ; i < children.size(); i++ )
children[i]->preorder( f ) ; // exec f on each child
}
} ;
template <typename T>
struct Tree
{
TreeNode<T>* root;
// TREE LEVEL functions
void clear() { delete root ; root=0; }
void insert( T* data ) { if(root)root->insert(data); }
} ;
现在通常,您有预订和后序遍历作为TreeNode
的递归成员函数,如上所示。 但是说你不想传递函数,你想从外面访问树中的每个节点类(即只是给出一个Tree
对象)。
你怎么能这样做?
答案 0 :(得分:3)
我会通过定义一个PreorderIterator
类来解决这个问题,该类保持状态在遍历中的位置。它将具有返回当前节点和在遍历中前进一步的方法。
如果树结构在迭代器的生命周期中发生变异,则必须小心。也许树可以保持修改计数;迭代器可以在开始时捕获计数并检查每次访问时的更改(如果找到则抛出异常)。
答案 1 :(得分:2)
一种简单的方法是将树加载到列表中,然后在需要时遍历列表。该列表只是一个指针列表,因此并不昂贵。为此,您将使用the trie traversal algorithm的修改版本:
void traverse(Node n){
if(null == n) return;
for( Node c: n.children){
visit( c );
traverse( c );
}
}
您可以使用visit
来实际加载您的列表。像
List<Node> getListToIterate(Node n){
List<Node> result = new ArrayList<Node>();
traverse(n,resutl);
return result;
}
void traverse(Node n, List list){
if(null == n) return;
for( Node c: n.children){
list.add( c );
traverse( c );
}
}
此外,如果您决定,可以将此算法包装在TreeIterator
类中,该类将跟踪您在列表中的位置。