如何遍历n-ary树作为迭代器或流

时间:2016-01-12 23:02:39

标签: scala

我想在我的Tree类中创建一个函数来遍历一个n-ary Tree [T]以获取一个带有(level,T)的元组,以便该Tree的用户可以执行类似

的操作
tree.traverse.foreach{ case(l, t) => printf("%-30s %s", "  "*l + t.id, info(t))

获取此类报告

rootnode                       
  n1.0                         
    n1.0.1                     >> n1.0.1
    n1.0.2                     >> n1.0.2
    n1.0.3                     >> n1.0.3
  n3.0                         
    n3.0.1                     >> n1.0.1
      n3.0.1.1                 >> n1.0.1

树节点是

class TreeNode[T](val id: String, 
          private var _data: Option[T],
          private var _parent: String, 
          private var _treeNodeType: TreeNodeType) {
  private var _children: Set[String] = Set()
  ...
}

我可以使用traverse或traversef递归遍历树

class Tree[T] {
  private val ROOT = "rootnode"
  val rootNode = new TreeNode(ROOT, None.asInstanceOf[Option[T]], "", ROOTNODETYPE)
  var hmTree: HashMap[String, TreeNode[T]] = HashMap(ROOT -> rootNode)

def traverse: Unit = {
  def iter(s: String, l: Int): Unit = {
    val n = hmTree(s)
    printf("%-30s\n", "  "*l + n.id)
    n.children.foreach(c => iter(c, l+1))
  }
  iter(ROOT, 0)
}

def traversef(f: Option[T] => String): Unit = {
  def iter(s: String, l: Int): Unit = {
    val n = hmTree(s)
    printf("%-30s %s\n", "  "*l + n.id, f(n.data))
    n.children.foreach(c => iter(c, l+1))
  }
  iter(ROOT, 0)
}

...

我查看了http://www.scala-lang.org/old/node/11275.html(问题:如何使用Streams实现对n-ary树的延迟遍历?)但无法使代码生效。绊倒我的是如何Stream.cons孩子们。

我可以使用流或迭代器。关键是在Tree类中定义遍历方法并在外部使用它。

提前致谢。

更新

非常感谢@Archeg - 这是工作遍历

def traverse(t: TreeNode[T], depth: Int = 0): Stream[(TreeNode[T], Int)] = {  
  (t, depth) #:: t.children.foldLeft(Stream.empty[(TreeNode[T], Int)]) { 
          case (aggr, el) => aggr #::: traverse(hmTree(el), depth+ 1)   
  }
}

tree.traverse(tree.rootNode).
  foreach{ case(t, l) => printf("%-30s %s\n", "  "*l + t.id, t.id) }

1 个答案:

答案 0 :(得分:2)

我已经很简单,所以很容易理解:

 case class Tree[T](data: T, children: List[Tree[T]])

 def traverse[T](t: Tree[T]): Stream[T] =
    t.data #:: t.children.foldLeft(Stream.empty[T])((aggr, el) => aggr #::: traverse(el))

<强> UPD

略微修改的版本,为您提供缩进:

def traverseInd[T](t: Tree[T], depth: Int = 0): Stream[(T, Int)] =
    (t.data, depth) #:: t.children.foldLeft(Stream.empty[(T, Int)]) { 
            case (aggr, el) => aggr #::: traverseInd(el, depth+ 1)
    }