在Haskell搜索玫瑰树

时间:2012-06-02 18:15:04

标签: haskell

我正在尝试编写一个函数来搜索玫瑰树中的给定元素并返回它的位置。

当我向您展示我已经拥有的内容时,可能会更清楚:

给定一个定义的树:

数据树文本=节点值                        [树值]

例如:

test = Node "1" [
          Node "11" [
               Node "111" [], 
               Node "112" [
                  Node "1121" [], Node "1122" [], Node "1123" []
               ]
          ], 
          Node "12" []
      ]


            1
      11         12
111      112    
     1121 1122 1123   

我正在寻找功能搜索:

search :: String -> Tree String -> [Integer]

搜索1123测试 - >应该返回[1,2,3]
- 第一个子树1 = 11 - >第二个子树11 = 112,第三个子树112 = 1123

我知道如何遍历树,

display (Node v xs) = v ++ concatMap display xs

但是我不知道如何将整数值分配给子树数组的每个元素,并且还从树的上部到下部递归地传递它。 你们可以指导我在哪里/如何寻找解决方案?我对Haskell很新。

1 个答案:

答案 0 :(得分:4)

最简单的方法是让函数返回具有所需数据的节点的所有路径的列表(我想,树中应该只有一个,但是这并不重要)首先,然后使用第一个:

searchList :: (Eq a) => a -> Tree a -> [[Integer]]
searchList val (Node dat subs)
    | val == dat = [[]]  -- empty path
    | otherwise  = concat [map (c:) (searchList val t) | (c,t) <- zip [1 .. ] subs]

search :: Eq a => a -> Tree a -> [Integer]
search val t = case searchList val t of
                 (p:_) -> p
                 _ -> error "Value not found"

如果Daniel Wagner的怀疑是正确的并且您的树木是尝试的,您可以更有效地搜索,但原则保持不变,但是,因为我们现在知道我们要么有一个节点具有所需数据,要么没有,结果是更恰当的是Maybe [Integer]

import Data.List (isPrefixOf)
import Control.Monad -- for the MonadPlus instance of Maybe

searchTrie :: String -> Tree String -> Maybe [Integer]
searchTrie target (Node val subs)
    | val == target = Just []
    | val `isPrefixOf` target = case dropWhile smaller (zip [1 .. ] subs) of
                                  ((c,t):_) -> fmap (c:) $ searchTrie target t
                                  _ -> Nothing
    | otherwise = Nothing
      where
        smaller (_,Node v _) = v < take (length v) target