scala n-arity tree tail递归评估

时间:2016-12-21 00:48:33

标签: scala recursion tree tail-recursion

我有一个Tree结构,它比二叉树结构更通用

sealed trait Tree[+A]

case class Leaf[A](value: Terminal[A]) extends Tree[A]
case class Node[A](op: Function[A], branches: Tree[A]*) extends Tree[A]

如您所见,它可以有任意数量的分支。

我试图将评估方法设为尾递归,但我无法做到。

def evaluateTree[A](tree: Tree[A]): A = tree match {
  case Leaf(terminal) => terminal.value
  case Node(op: Function[A],  args @ _*) => op.operator((for (i <- args) yield evaluateTree(i)))
}

如何手动保存堆栈?

2 个答案:

答案 0 :(得分:1)

如果每个Node可以保留不同的op,那么不,我不认为尾递归是可能的。

另一方面,如果您可以将所有Leaf.value个信息提供给单个op,那么可能会这样做。

def evaluateTree[A](tree: Tree[A]): A = {
  @tailrec
  def allValues(branches: Seq[Tree[A]], acc: Seq[A] = Seq()): Seq[A] =
    if (branches.length < 1) acc
    else branches.head match {
      case Leaf(term) => allValues(branches.tail, term.value +: acc)
      case Node(_, args: Seq[Tree[A]]) => allValues(branches.tail ++ args, acc)
    }

  tree match {
    case Leaf(terminal) => terminal.value
    case Node(op: Function[A], args: Seq[Tree[A]]) => op.operator(allValues(args))
  }
}

我无法编译,因为我没有TerminalFunction的定义,但它应该是解决问题的一种方法的合理概述。

答案 1 :(得分:0)

实际上,使用深度优先搜索是可能的。

$('.save').click(function(e){
    var row = $(this).closest('tr');
    var id = row.find('.id').text();
    var x = row.find('.x').text()
});