我想找到STree
的深度,但在我的代码中,它不会计算第一级。
data STree = SNode Label [STree] deriving (Eq,Show)
tdepth :: STree -> Label
tdepth (SNode _ [])= 0
tdepth (SNode l s) = 1 + naiveSumList([tdepth t | t <- s])
naiveSumList :: [Int] -> Label
naiveSumList (x:xs) = x + (naiveSumList xs)
naiveSumList [] = 0
tdepth SNode _ []
必须提供1,但我如何计算等级?以下是{I}我一直在测试的STree
:
s1 = SNode 1 []
s2 = SNode 1 [
SNode 2 [],
SNode 3 []
]
s3 = SNode 1 [
SNode 2 [
SNode 4 [],
SNode 5 [],
SNode 6 []
],
SNode 3 []
]
s4 = SNode 1 [
SNode 2 [
SNode 4 [],
SNode 5 [
SNode 7 []
],
SNode 6 []
],
SNode 3 []
]
我的代码示例结果:
tdepth s1 = 0
tdepth s2 = 1
tdepth s3 = 2
tdepth s4 = 3
结果应该是:
tdepth s1 = 1
tdepth s2 = 2
tdepth s3 = 3
tdepth s4 = 4
答案 0 :(得分:4)
让我们从基础案例开始。您希望tdepth (SNode label [])
返回1
,所以让我们写下这个案例:
tdepth :: STree -> Int
tdepth (SNode _ []) = 1
现在我们需要知道如何计算树的深度。树的深度是最长分支上的节点数,您对函数的期望的例子正是我们正在寻找的。由于我们正在寻找最长的分支,我们应该找到每个分支的最大深度。幸运的是,Prelude
已经内置了maximum :: Ord a => [a] -> a
函数,因此我们可以
tdepth (SNode _ branches) = 1 + maximum [tdepth branch | branch <- branches]
或等效(以及我喜欢的版本)
tdepth (SNode _ branches) = 1 + maximum (map tdepth branches)
但是,我不喜欢map tdepth branches
周围的括号,因为我们正在使用Int
,我们可以使用succ
函数,只需将{1}添加到Int
传递给它:
tdepth (SNode _ branches) = succ $ maximum $ map tdepth branches
但是你可以使用你喜欢的任何版本,这三个版本几乎相同。
我们现在一起
tdepth :: STree -> Int
tdepth (SNode _ []) = 1
tdepth (SNode _ branches) = 1 + maximum (map tdepth branches)
我还有一个问题,我们已经重复了我们对单个节点深度的逻辑,我们有什么方法可以将这个问题减少到我们Don't Repeat Ourselves的位置?如果不是检查基本情况,我们找出了maximum
如果0
返回branches == []
的方法,那么我们的函数就不需要两个语句。不幸的是,如果传递一个空列表,maximum
当前会出错,但我们可以简单地解决这个问题。我们所要做的就是确保传递给maximum
的列表中始终至少包含一个元素:
tdepth :: STree -> Int
tdepth (SNode _ branches) = 1 + maximum (0 : map tdepth branches)
-- Or if you prefer
-- = succ $ maximum $ 0 : map tdepth branches
我们可以安全地将0
添加到我们的深度,因为我们知道我们的深度将始终大于0,因此在该列表上调用maximum
将返回有效结果。现在我们有一个表达式可以准确计算树的深度而无需处理任何特殊情况。