在 Haskell 中搜索玫瑰树

Posted

技术标签:

【中文标题】在 Haskell 中搜索玫瑰树【英文标题】:Searching rose tree in Haskell 【发布时间】:2012-06-07 13:12:20 【问题描述】:

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

当我向你展示我已经得到的东西时可能会更清楚:

给定一棵有定义的树:

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

例如:

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】:

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

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

【讨论】:

我认为他正在存储一个 trie,它承认搜索效率更高。 这确实是一个尝试,我应该提到它。这两种方法对我来说都很好,而且速度惊人。我很惊讶!谢谢丹尼尔! 这让我思考..如何成为如此高效的haskell程序员..当我分析你的解决方案时它是如此简单,但我自己却很难解决它..我真的花了好几个小时一个.. Haskell 作为一个初学者对我来说是一场斗争,这令人沮丧,因为我真的很喜欢它.. 我可能应该提出另一个问题“如何成为一名 Haskell 程序员”;) @user1432699 最后一个问题的答案很简单:练习。使用它,当你遇到问题时提出问题,然后你会变得越来越好。取决于您的思维方式,可能需要更长时间或更快,但会取得进展。

以上是关于在 Haskell 中搜索玫瑰树的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Haskell 中实现 B+ 树?

在 Haskell 中不变异树

Haskell 2-3-4 树

如何在 Haskell 中表示两棵树之间的映射?

Haskell 总结了通过树的所有路径

解释 Haskell 广度优先编号代码遍历树