使用尾部递归和匹配案例遍历Scala中的二叉树

使用尾部递归和匹配案例遍历Scala中的二叉树,scala,pattern-matching,binary-tree,binary-search-tree,tail-recursion,Scala,Pattern Matching,Binary Tree,Binary Search Tree,Tail Recursion,我在scala中将一个case类定义为 case class Node(key: String, value: String, var left: Node, var right: Node) 我尝试使用尾部递归和匹配用例而不是循环和if语句遍历它。我当前的遍历方法如下: def find(key:String, tree:Node): Option[String] = { if(tree == null) { return None } else if (tr

我在scala中将一个case类定义为

case class Node(key: String, value: String, var left: Node, var right: Node)
我尝试使用尾部递归和匹配用例而不是循环和if语句遍历它。我当前的遍历方法如下:

def find(key:String, tree:Node): Option[String] = {
    if(tree == null) {
        return None
    } else if (tree.key == key) {
        return Some(tree.value)
    }
    val checkLeft = find(key, tree.left)
    val checkRight = find(key, tree.right)
    if(checkLeft != None) {
        return checkLeft
    } else if(checkRight != None) {
        return checkRight
    }
    return None
}
我最好如何使用尾部递归来创建匹配

我目前有:

key match {
    case tree.key => Some(tree.value)
    case _ => find(key, tree.left)
}
但很明显,这不会正确地遍历我的整个树

case class Node(key: String, value: String, var left: Node, var right: Node)

object Tree
{
    def find(key: String, tree: Node): Option[String] =
    {
        @tailrec
        def find_with_accumulator(key: String, node_list: List[Node]): Option[String] =
        {
            node_list match
            {
                case Nil => None
                case Node(k, value, left, right) :: rest =>
                    if (k == key) Some(value)
                    // .flatten removes all the None and unwraps the Options
                    else
                    {
                        find_with_accumulator(key, List(left, right).filter(_ != null) ++ rest)
                    }
            }
        }

        find_with_accumulator(key, List(tree))
    }
}
改编自

我建议更改树的表示形式,如下所示:

sealed abstract class AbstractNode

case class EmptyNode() extends AbstractNode

case class Node(key: String, value: String, left: AbstractNode, right: AbstractNode) extends AbstractNode

object Tree
{
    def find(key: String, tree: AbstractNode): Option[String] =
    {
        @tailrec
        def find_with_accumulator(key: String, node_list: List[AbstractNode]): Option[String] =
        {
            node_list match
            {
                case Nil => None
                case EmptyNode() :: rest => find_with_accumulator(key, rest)
                case Node(k, value, left, right) :: rest =>
                    if (k == key) Some(value)
                    else find_with_accumulator(key, left :: right :: rest)
            }
        }

        find_with_accumulator(key, List(tree))
    }
}

您正在尝试实现二进制搜索树吗?通常,这些分支的属性是左分支上的所有内容都小于当前键,右分支上的所有内容都大于键,因此只需要在一个分支上递归。否则,拥有一棵树就没有多大意义了。其次,如果表达式在函数式编程中完全正确,但我们倾向于避免显式返回。只是一个提示,如果您想实现任何尾部递归,请记住这一点,您可能需要使用累加器。我猜OP(单向地)使用
null
表示空树,基于此:
if(tree==null){return None…
我同意它不是惯用的,但是树已经有了相当大的内存开销,有时它可以帮助减少内存开销(在这种特殊情况下,使用case对象可能可以避免)。有时纯度是要付出代价的,这是一个权衡问题。我同意
EmptyNode
应该是
case对象
@SethTisue。谢谢你的提示。我还不完全熟悉Scala,因为我读Scala教程才一周。