你看过 Chris Okasaki 的“广度优先编号:算法设计小练习的教训”吗?该Data.Tree
模块包括一个名为的一元树构建器,该构建器unfoldTreeM_BF
使用改编自该论文的算法。
这是我认为与您正在做的事情相对应的示例:
假设我想搜索一个无限二叉树的字符串,其中所有左孩子都是父字符串加“a”,右孩子是父字符串加“bb”。我可以使用unfoldTreeM_BF
搜索树广度优先并将搜索到的树返回到解决方案:
import Control.Monad.State
import Data.Tree
children :: String -> [String]
children x = [x ++ "a", x ++ "bb"]
expand query x = do
found <- get
if found
then return (x, [])
else do
let (before, after) = break (==query) $ children x
if null after
then return (x, before)
else do
put True
return (x, before ++ [head after])
searchBF query = (evalState $ unfoldTreeM_BF (expand query) []) False
printSearchBF = drawTree . searchBF
这不是非常漂亮,但它有效。如果我搜索“aabb”,我会得到我想要的:
|
+- a
| |
| +- aa
| | |
| | +- aaa
| | |
| | `- aabb
| |
| `- abb
|
`- bb
|
+- bba
|
`- bbbb
如果这是您所描述的那种事情,那么适应您的树类型应该不难。
更新:这是一个免费的版本expand
,以防您遇到这种情况:
expand q x = liftM ((,) x) $ get >>= expandChildren
where
checkChildren (before, []) = return before
checkChildren (before, t:_) = put True >> return (before ++ [t])
expandChildren True = return []
expandChildren _ = checkChildren $ break (==q) $ children x
(感谢 camccann 促使我摆脱旧的控制结构习惯。我希望这个版本更容易接受。)