假设我有一个二叉树:
data Bst a = Empty | Node (Bst a) a (Bst a)
我必须编写一个搜索值并返回其子项数的函数。如果没有具有此值的节点,则返回-1。我试图写BFS和DFS,但两者都失败了。
答案 0 :(得分:2)
模式匹配是你的朋友。您的Bst
可以是Empty
或Node
,因此在顶层,您的search
功能将
search Empty = ...
search (Node left x right) = ...
Empty
树可能包含目标值吗?使用Node
目标值(如果存在)将是x
子树中的left
子树中的节点值(right
以上),或者可能是某些这些的组合。
通过“返回其子项的数量”,我假设您的意思是Bst
的后代总数,其中Node
以numChildren
为根,其值为目标,这是一个有趣的问题的组合。您将需要另一个函数,例如Empty
,其定义使用上述模式匹配。考虑:
Node
树有多少个后代?x
案例中,left
不计算在内,因为您需要后代。如果您只有一个函数来计算right
和{{1}}子树中的子项数... 答案 1 :(得分:1)
这是一种方法。呼吸优先搜索实际上实现起来有点棘手,这个解决方案(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