Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell-查找节点值的路径_Haskell_Tree_Nodes - Fatal编程技术网

Haskell-查找节点值的路径

Haskell-查找节点值的路径,haskell,tree,nodes,Haskell,Tree,Nodes,这个问题的问题是: 树保存类型a的数据。函数findpath给定函数f、一些数据x和树t,将t中的路径列表(可能为空)返回到形式为Node d的节点,其中fd等于x 此问题中使用的数据类型的声明结构: data Btree a = ND | Data a | Branch (Btree a) (Btree a) deriving (Show,Eq) data Dir = L | R deriving (Show,Eq) type Path = [Di

这个问题的问题是:

树保存类型a的数据。函数findpath给定函数f、一些数据x和树t,将t中的路径列表(可能为空)返回到形式为Node d的节点,其中fd等于x

此问题中使用的数据类型的声明结构:

data Btree a = ND | Data a |  Branch (Btree a) (Btree a)
           deriving (Show,Eq)

data Dir = L | R 
       deriving (Show,Eq)

type Path =  [Dir]
我尝试解决此函数:

findpath :: Eq b => (a -> b) -> b -> Btree a -> [Path]
findpath f x (Data d)                = [[]]
findpath f x ND                      = [[]]
findpath f x (Branch (Data d) right) = [[L]] ++ (findpath f x right)
findpath f x (Branch left (Data d))  = [[R]] ++ (findpath f x left)
1. findpath (2*) 3 tree2
2. findpath (2*) 2 tree2
3. findpath (2*) 3 tree1
用于测试的数据:

tree1 = Branch ND ND
tree2 = Branch ND (Data 3)
tree3 = Branch tree1 tree2
用于测试函数的函数调用:

findpath :: Eq b => (a -> b) -> b -> Btree a -> [Path]
findpath f x (Data d)                = [[]]
findpath f x ND                      = [[]]
findpath f x (Branch (Data d) right) = [[L]] ++ (findpath f x right)
findpath f x (Branch left (Data d))  = [[R]] ++ (findpath f x left)
1. findpath (2*) 3 tree2
2. findpath (2*) 2 tree2
3. findpath (2*) 3 tree1
它给出的输出是:

1. [[R],[]]
2. [[R],[]] - incorrect
3. Throws exception

如果您对findpath函数有任何帮助,我们将不胜感激

让我们一次处理一个案例,完全使用
Btree
的数据定义中的案例。就是因为

data Btree a = ND | Data a | Branch (Btree a) (Btree a)

那么我们将完全考虑以下形状的树木,而没有其他形状:

  • ND
  • 数据d
  • 分支机构l/r
  • 让我们开始吧

    findpath f x ND = {- TODO -}
    
    回想一下规格:

    函数findpath给定函数f、一些数据x和树t,将t中的路径列表(可能为空)返回到表单数据d的节点,其中fd等于x

    (我假设您在写“节点d”的地方,您的意思是“数据d”,以符合您对树的定义,并将“列表”更改为“列表”。)

    在当前情况下,我们有
    f
    x
    ,如前所述,以及
    t=ND
    。将这些内容替换为我们应该返回的内容,我们得到:

    ND中指向表单数据d节点的路径列表,其中

    由于
    ND
    不包含任何形式为
    Data d
    的节点,因此不存在此类路径。因此:

    findpath f x ND = []
    
    findpath f x (Data d) = if f d == x
        then [[]]
        else []
    
    下一个案例:

    findpath f x (Data d) = {- TODO -}
    
    现在我们有了
    t=Data d
    。再次修改规范,我们必须返回

    Data d
    中到表单Data d节点的路径列表,其中fd等于x

    好的,那么我们必须检查
    fd
    是否等于
    x
    ,嘿

    findpath f x (Data d) = if f d == x
        then {- TODO -}
        else {- TODO -}
    
    如果
    fd==x
    ,那么表单数据d的节点正好有一条路径,其中fd等于x——即空路径。如果不是
    fd==x
    ,那么就没有这样的路径。因此:

    findpath f x ND = []
    
    findpath f x (Data d) = if f d == x
        then [[]]
        else []
    
    最后一种情况是:

    findpath f x (Branch l r) = {- TODO -}
    
    再次修改规范,现在使用
    t=Branch l r
    ,我们必须返回

    分支lr
    中指向表单数据d节点的路径列表,其中fd等于x

    现在你可能觉得有点卡住了。毕竟,
    l
    r
    是如此普遍,以至于很难知道是否有到表单数据d节点的路径,对吗?那么,您如何才能发现是否有一条进入分支l r的路径最终在数据d节点处结束?当然,如果只有一种方法可以找到这两个子问题的答案,也许我们可以扩大这些路径,嘿

    幸运的是,我们有一个函数可以回答这个子问题:
    findpath
    本身。那么,让我们回答这些子问题,然后思考该怎么做

    findpath f x (Branch l r) = {- TODO -} where
        pathsInL = findpath f x l
        pathsInR = findpath f x r
    
    好的,我们在树
    l
    中有一些路径,它们指向
    Data d
    形式的节点,其中
    fx
    等于
    d
    (分别是树
    r
    中的一些路径)。我们如何将这些路径转换为树
    分支lr
    中的路径?简单:通过将
    L
    (分别为
    R
    )预加到每个路径。然后我们可以将这两个路径集合组合在一起

    此时,我将停止提供代码:我认为您缺少的关键洞察应该已经在上面提供的递归框架中了。但是,我将建议一些功能,您可能会发现这些功能在充实骨架的最后一部分时很有用:

  • (:)
    可用于将新的
    目录
    预先添加到
    路径
  • map
    可用于将修改单个
    路径的函数升级为修改整个
    路径列表的函数
  • (++)
    可用于连接两个
    路径列表
    s,生成一个包含其两个参数中每个参数的所有元素的列表

  • 试一试,让我们知道你下一步会被困在哪里

    findpath fx(数据d)
    的情况下,您不需要检查
    fd==x
    ?否则,
    f
    x
    将永远不会使用!这不是唯一的问题,但你可以开始解决这个问题。好吧,你首先要解决的问题是,你的路径列表永远不能为空,因为你的函数实际上都不会返回空列表。因此,您立即违反了自己的规范。你也从来没有真正检查过你的
    x
    是否等于
    d
    ,所以你得到的路径当然是错误的。这个问题比你以前的草稿有了很大的改进,干得好!作为提示,请尝试处理一般情况
    findpath f x(Branch left right)
    ,其中
    left
    right
    可以是任意子树。现在,您需要其中一个是
    数据…
    ,但情况并非总是如此。您需要使用递归并小心地在正确的位置添加一些
    L
    R
    。可能一些列表的串联会很有用。当你是一个初学者的时候,这不是一件小事,所以如果你一开始看不到解决方案,不要惊慌。顺便说一句,我认为这个函数的规格不是很好。我更喜欢类型签名
    findpath::(a->Bool)->b树a->[Path]
    ,并将规范中的“其中fd等于x”替换为“其中fd为真”。这样,如果调用方愿意,可以使用完全相等以外的其他谓词。当然,
    findpath的两种形式可以通过
    findpathDA fx=findpathDW((x==).f)
    findpathDW p=findpathDA p True
    很容易地相互转换,但仍然如此。@DrAnonymous哈哈,哇!在
    datad
    案例中,我没有将规范正确地翻译成代码。你能发现这个错误吗?=)那么这个bug就在