我有一个不规则定义的树,我如何通过它来找到它的最大值?
我的策略是建立一个列表并取出更大的价值,我的问题是,我只知道二叉树,我有左边和右边,像这样:Node x Empty Empty
我现在有这个结构:
tree= No 2 [No 3 [No 6 []], No 4 [No 7 [], No 8 []], No 5 []]
data TreeIrr a = No a [TreeIrr a]
它应该如何遍历?
这是我能做的最好的事情:
maxi :: ArvIrr a -> [a]
maxi (No a []) = [a]
maxi (No a l@((No b []):z)) = [a]++[b]++(maxis l)
where
maxis ((No x k):(No y z):ls) = [y]++maxis ls
maxi (No a [k]) = [a]++(maxi k)
答案 0 :(得分:4)
data TreeIrr a = No a [TreeIrr a]
这种树的最大元素是两个值中的最大值:
因此:
treeMaximum :: Ord a => TreeIrr a -> a
treeMaximum (No a []) = a
treeMaximum (No a children) = max a (maximum (map treeMaximum children))
max :: Ord a => a -> a -> a
和maximum :: Ord a => [a] -> a
是标准库函数。
答案 1 :(得分:3)
让我们假装我们有一个遍历函数:
maxi :: ArvIrr a -> [a]
我们应该如何将其扩展到树的列表?
maxiList :: [ArvIrr a] -> [a]
好吧,我们可以使用map
:
maxiList l = map maxi l -- WRONG type [[a]]
但是我们得到的是列表而不是单个列表。没问题,让我们把它们连接起来。
maxiList l = concat (map maxi l)
好的,现在让我们假设我们maxiList
正在工作,并根据它构建maxi
。这很简单:
maxi (No a l) = a : maxiList l
所以,把所有东西放在一起:
maxi :: ArvIrr a -> [a]
maxi (No a l) = a : maxiList l
maxiList :: [ArvIrr a] -> [a]
maxiList l = concat (map maxi l)
我们可以通过删除maxiList
并内联它来进一步简化它。
maxi :: ArvIrr a -> [a]
maxi (No a l) = a : concat (map maxi l)
并且concat (map maxi l)
可以重写为concatMap maxi l
,
利用concatMap
库函数。
maxi :: ArvIrr a -> [a]
maxi (No a l) = a : concatMap maxi l
要计算最大值,您可以使用
maxInTree :: Ord a => ArvIrr a -> a
maxInTree t = maximum (maxi t)
如果需要,可以进一步简化此代码,以便甚至不构建中间列表,并直接计算最大值。对于Haskell初学者来说这可能有点挑战,但它可能很有趣。首先,在上面的代码中替换concat
...
答案 2 :(得分:2)
只需使用简单的递归式dfs遍历:
data TreeIrr a = No a [TreeIrr a]
findMax :: Ord a => TreeIrr a -> a
findMax (No x []) = x -- For a tree without subtrees the maximum is it's value
findMax ( No x subtrees ) =
maximum ( x : map findMax subtrees) -- For a tree with subtrees the maximum is the maximum among it's root value or the maximum of it's subtrees
然后
>> findMax (No 2 [No 3 [No 6 []], No 4 [No 7 [], No 8 []], No 5 []])
8
UPD: 经过一番思考后,基本情况在这里是多余的。所以 只是
findMax :: Ord a => TreeIrr a -> a
findMax ( No x subtrees ) = maximum ( x : map findMax subtrees)
可以正常使用