haskell - 检查二叉树是否完整 - haskell
问题描述
我有一个二叉树:
data Btree a = Leaf a | Unary (Btree a) a | Binary (Btree a) a (Btree a) deriving Show
以及一些可以使用的示例:
ex1 = Binary (Binary (Leaf 0) 1 (Leaf 2)) 3 (Unary (Leaf 4) 5)
ex2 = Binary (Unary (Leaf 1) 2) 3 (Binary (Leaf 4) 5 (Leaf 10))
ex3 = Binary (Binary (Leaf (0,"a"))(1,"z")(Leaf (2,"x")))(3,"y")(Binary (Leaf (4,"b"))(5,"c")(Leaf (6,"d")))
我需要找出这棵树是否完整,如果根与任何叶子之间的距离始终相同,直到 1,那么一棵树是完整的,所有最深的叶子都位于其他叶子的左侧,并且有最多是一个内部节点,其中一元节点应位于倒数第二级。
这就是我到目前为止所拥有的
complete :: Btree a -> Bool
complete x = fst $ go x where
go (Leaf _) = (True, 0)
go (Unary left _) = (leftTrue, 1 + leftCount) where
(leftTrue, leftCount) = go left
go (Binary left _ right) = (leftTrue && rightTrue &&
leftCount == rightCount,
1 + leftCount + rightCount) where
(leftTrue, leftCount) = go left
(rightTrue, rightCount) = go right
ex1 & ex3 应该返回 true,但只有 ex3 是。我相信一元部分是问题所在。
解决方案
这个答案依赖于以下
Unary
部分的代码更改:(leftTrue, 1 + leftCount)
->(False, 1 + leftCount)
。
您的解决方案的主体是go
功能。如果左右子树完全平衡以及子树有多少节点,则该函数返回子树。所有深度都相同,就像在 ex3 中一样。但是如果你没有 2^n-1 个节点和 2^(n-1) 个叶子,就不可能构建那棵树。在您的问题的描述中,允许表示任何节点数的不平衡很少。Ex1 满足 ex2 不满足的规则。根据您的定义,Ex3 也是完整的。
在代码下,我对示例进行了 ASCII 艺术。
我的解决方案不计算子树的数量节点。它计算最大和最小深度,因为它允许我揭示树的任何级别的非法不平衡。布尔值表示子树是否满足完整树的条件。它检查:
- 差异最多相同
- 左子树的最小深度大于或等于右树的最大深度。
上面的检查还包含关于倒数第二级的一个一元节点的条件。
你能猜出这个地方属于什么......吗?
data Btree a = Leaf a | Unary (Btree a) a | Binary (Btree a) a (Btree a) deriving Show
ex1 = Binary (Binary (Leaf 0) 1 (Leaf 2)) 3 (Unary (Leaf 4) 5)
ex2 = Binary (Unary (Leaf 1) 2) 3 (Binary (Leaf 4) 5 (Leaf 10))
ex3 = Binary (Binary (Leaf (0,"a"))(1,"z")(Leaf (2,"x")))(3,"y")(Binary (Leaf (4,"b"))(5,"c")(Leaf (6,"d")))
complete :: Btree a -> Bool
complete x = fst $ go x
go :: Btree a -> (Bool,(Int,Int))
go (Leaf _) = (True, (0, 0))
go (Unary left _) = (leftMaxDepth == 0, (1 + leftMaxDepth, 0)) where
(leftIs, (leftMaxDepth, leftMinDepth)) = go left
go (Binary left _ right) =
( leftIs && rightIs
...
, (1+newMaxDepth
, 1+newMinDepth )) where
newMaxDepth = max leftMaxDepth rightMaxDepth
newMinDepth = min leftMinDepth rightMinDepth
(leftIs, (leftMaxDepth, leftMinDepth)) = go left
(rightIs, (rightMaxDepth, rightMinDepth)) = go right
&& leftMinDepth >= rightMaxDepth && newMaxDepth - newMinDepth <= 1
例 1:真
3
/ \
/ \
1 5
/ \ /
0 2 4
深度:[3,3,3,2]
例 2:错误
3
/ \
/ \
2 5
/ / \
1 4 10
深度:[3,2,3,3]
例 3:是的
(3,"y")
/ \
/ \
(1,"z") (5,"c")
/ \ / \
(0,"a") (2,"x") (4,"b") (6,"d")
深度:[3,3,3,3]
推荐阅读
- sonata-admin - 删除 SonataAdmin 徽标
- java - ArchiveException:归档程序同时将参数传递给 Jar 文件
- mongodb - 获取 MongoDB 集合的数组中嵌入文档的总数
- scala - 当DataFrame为空时抛出AnalysisException(没有这样的结构字段)
- swift - 如何使用 Alamofire (post) 上传图片?
- firebase-realtime-database - AuthUI 的初始导航视图控制器在 Xcode 10.2 下不起作用
- c# - 从 WCF 运行 Exe
- sql - SQL 行在不同组中聚合每次文本出现在日志中
- javascript - 如何使用jsPDF-autotable从pdf标题中的路径显示图像
- matplotlib - 如何使用 PyPlot 在 Atom 中显示图形