假设我有一个二叉树:
data Bst a = Empty | Node (Bst a) a (Bst a)
我必须编写一个函数来搜索一个值并返回其子项的数量。如果没有具有此值的节点,则返回 -1。我试图同时编写 BFS 和 DFS,但我都失败了。
假设我有一个二叉树:
data Bst a = Empty | Node (Bst a) a (Bst a)
我必须编写一个函数来搜索一个值并返回其子项的数量。如果没有具有此值的节点,则返回 -1。我试图同时编写 BFS 和 DFS,但我都失败了。
模式匹配是你的朋友。您Bst
可以是Empty
或 a Node
,因此在顶层,您的search
功能将是
search Empty = ...
search (Node left x right) = ...
一Empty
棵树可能包含目标值吗?Node
目标值(如果存在)将是节点值(上x
图)、left
子树中、right
子树中——或者可能是这些的某种组合。
Bst
通过“返回 [ing] 其子项的数量”,我假设您是指以 a 为目标的子节点的总数Node
,这是一个有趣的问题组合。您将需要另一个函数,例如numChildren
,其定义使用上述模式匹配。注意事项:
Empty
一棵树有几个后代?Node
情况下,x
不算数,因为您想要后代。如果你有一个函数来计算子树left
和right
子树中的孩子的数量……这是一种方法。呼吸优先搜索实际上可能有点难以实现,而且这个解决方案 (findBFS) 非常复杂(附加到列表是 O(n)),但你会明白要点的。
首先,我决定拆分查找函数以返回节点元素匹配的树。这简化了拆分计数功能。此外,返回元素的数量比返回后代的数量更容易,如果找不到则返回 -1,因此numDesc
函数依赖于 numElements 函数。
data Tree a = Empty
| Node a (Tree a) (Tree a)
numElements :: Tree a -> Int
numElements Empty = 0
numElements (Node _ l r) = 1 + numElements l + numElements r
findDFS :: Eq a => a -> Tree a -> Tree a
findDFS _ Empty = Empty
findDFS x node@(Node y l r) | x == y = node
| otherwise = case findDFS x l of
node'@(Node _ _ _) -> node'
Empty -> findDFS x r
findBFS :: Eq a => a -> [Tree a] -> Tree a
findBFS x [] = Empty
findBFS x ((Empty):ts) = findBFS x ts
findBFS x (node@(Node y _ _):ts) | x == y = node
findBFS x ((Node _ l r):ts) = findBFS x (ts ++ [l,r])
numDescDFS :: Eq a => a -> Tree a -> Int
numDescDFS x t = numElements (findDFS x t) - 1
numDescBFS :: Eq a => a -> Tree a -> Int
numDescBFS x t = numElements (findBFS x [t]) - 1