我正在尝试在Scala中创建一个非常简单的二叉树来进行数据存储和遍历。
现在我有:
trait Tree
case class Node(left: Tree, value: String, right: Tree) extends Tree
我的问题:
如何添加指向父级的指针?
我可以以任何方式左右指向null吗?或根节点的父指针?
我如何实际遍历树?
更新节点的值是否容易?
答案 0 :(得分:2)
不使用不可变的案例类。它是循环依赖:您需要父级来创建子级,但您还需要子级来创建父级。另一方面,大多数树遍历算法并不真正需要父代,因为父代通常在堆栈中或者可以存储在某个地方。
是的,我们通常使用特征的单例实例(object
)表示这些特征:
case object EmptyNode extends Tree
有很多算法,广度优先搜索和深度优先搜索是最常见的。实施它们是一个很好的练习。但是对于Scala方面的一些帮助,我们通常会在left
和right
上进行模式匹配,以了解我们下一步需要做什么:
tree: Tree match {
case EmptyNode => // do nothing, return, etc.
case Node(left, value, right) =>
// Do inorder, preorder, postorder operation order
// You will also probably be processing left and right as well
}
不,您的猜测是正确的,在树中使用不可变的案例类很难更新,因为如果更新叶节点,则必须重新创建它上面的所有内容。所谓的镜头和镜头库可以帮助你解决这个问题,尽管它们可能会更先进一些。 Scala中一个受欢迎的版本是Monocle。
看起来你刚开始编程或者是Scala的新手,所以我建议使用var
- s代替val
s:
case class Node(var left: Tree, var value: String, var right: Tree) extends Tree
此外,如果您的特征是密封的(sealed trait Tree
),那么编译器会告诉您是否在模式匹配中没有处理其中一个子类型。
修改强>
根据评论开始使用:
sealed trait Tree
case class Node(var left: Tree, var value: String, var right: Tree, var parent: Tree) extends Tree
case object EmptyNode extends Tree
答案 1 :(得分:0)
如果它对需要二叉树设施的程序员很有用,我写了一些可以继承和/或混合的Scala特性,以提供基本的红黑树功能,以及一些其他基于树的算法: