你怎么能迭代k-ary树?

时间:2013-03-05 22:05:12

标签: algorithm tree iteration

假设您有一个通用的k-ary树like this onethis 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对象)。

你怎么能这样做?

2 个答案:

答案 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类中,该类将跟踪您在列表中的位置。