我在Scala中使用case类和trait定义了一个二叉树结构。我这样做了:
staff
如果给定一个Tree实例,我想检查实例是否平衡,其中balance的定义是右边元素的数量等于左边元素的数量。
我尝试了以下方法(使用累加器模式)来获得我想要的东西:
sealed trait Tree[+T]
case class Node[A](v: A, l: Tree[A], r: Tree[A]) extends Tree[A]
case class Leaf[A](v: A) extends Tree[A]
case object Empty extends Tree[Nothing]
这会遇到一个无限循环,我很确定我的逻辑犯了一些愚蠢的错误。我对自己犯错误的地方并不自信。
答案 0 :(得分:5)
您的错误位于case Leaf
:它应该调用inner(Empty, acc)
。你拥有它的方式,它只是不断调用自己 - 因此是无限循环。
这将修复无限循环,但实现仍然是错误的:基本上,你继续下降左分支,递增左acc
,直到你击中叶子。然后你比较左右(仍然是零),并返回。除了树之外,此实现将始终返回false,这只是一个叶子节点。
另外,你对平衡树的定义是错误的。 例如,像这样:
A
/ \
B E
/ / \
C F G
/
D
匹配定义(左右三个元素),但不是很平衡 另一方面,这样的事情:
A
/
B
与定义不符,但实际上是平衡的。
平衡树的正确定义是一个,其中左右子树均衡,和它们的高度最多相差一个。
考虑到这一点,我们可以像这样编写一个正确的实现(如果它是平衡的,它返回树的高度,否则返回-1):
def balanced(root: Tree[_]): Int = root match {
case Empty => 0
case Leaf(_) => 1
case Node(_, left, right) =>
val l = balanced(left)
val r = balanced(right)
if (l < 0 || r < 0 || abs(l - r) > 1) -1 else (l max r) + 1
}