【问题标题】:In-order traversal of tree and apply given function to all nodes树的顺序遍历并将给定函数应用于所有节点
【发布时间】:2019-07-26 19:03:45
【问题描述】:

我写了一个中序树遍历函数:

let rec inOrder (tree: BinTree<'a>) : 'a list =
    match tree with
    | Leaf -> []
    | Node(x,l,r) -> (inOrder l) @ [x] @ (inOrder r)

现在我想使用这个函数来“映射”所有的音符,并应用一个作为参数给出的函数。它应该接受一个函数和一棵树,然后返回一棵树。这是我目前所拥有的:

let mapInOrder f t = 
    inOrder t
    |> Map.ofList

例如,如果我给函数这个输入:

mapInOrder float (Node(1,Node(2,Leaf,Leaf),Node(3,Leaf,Leaf)));;

我想要输出:

(Node(1.0,Node(2.0,Leaf,Leaf),Node(3.0,Leaf,Leaf)))

【问题讨论】:

    标签: .net functional-programming f#


    【解决方案1】:

    要将函数映射到List,请使用函数List.map

    let mapInOrder f t = 
        inOrder t
        |> List.map f
    

    但是这个函数会产生一个列表作为输出。你的例子会产生:

    [ 1.0 ; 2.0 ; 3.0 ]
    

    要生成您期望的输出,您的 mapInOrder 应该在将函数应用于每个元素后遍历生成另一棵树。

    【讨论】:

    • 是的,这就是我卡住的地方。所以我基本上应该对我的 inOrder 函数做一个修改版本?
    • 没错,如果您的输出需要是一棵树,那么它只是一个用于树的map 函数。它应该与您在inOrder 中的内容非常相似,只是它还接受函数f 作为参数并将其应用于每个元素。
    • 嗯,你能指出我正确的方向吗?到目前为止,这是我的想法let rec mapInOrder f (t: BinTree&lt;'a&gt;) = match t with | Node(x,l,r) -&gt; f(x) f(l) f(r)
    • Node(x, l, r) -&gt; Node(f x, mapInOrder f l, mapInOrder f r)
    【解决方案2】:

    这是我带来的:

    type BinTree<'a> =
        | Leaf 
        | Node of x :'a  * l:BinTree<'a> * r:BinTree<'a>
    
    let rec inOrder (tree: BinTree<'a>) : 'a list =
        match tree with
        | Leaf -> []
        | Node(x,l,r) -> (inOrder l) @ [x] @ (inOrder r)
    
    let exampleTree = (Node(1,Node(2,Leaf,Leaf),Node(3,Leaf,Leaf)));;
    
    let mapInOrder tree mapFunc = 
        tree
            |> inOrder 
            |> List.map mapFunc
    
    let res = mapInOrder exampleTree double
    //val res : double list = [2.0; 1.0; 3.0] <-------------- result of your current try
    
    let rec copyAndMapInOrder<'b> (tree: BinTree<'a>) mapFunc : BinTree<'b> =
        match tree with
        | Leaf -> Leaf
        | Node(x,l,r) -> Node((mapFunc x), (copyAndMapInOrder l mapFunc), (copyAndMapInOrder r mapFunc))
    
    let res2 = copyAndMapInOrder exampleTree double
    //val res2 : BinTree<double> = Node (1.0,Node (2.0,Leaf,Leaf),Node (3.0,Leaf,Leaf)) <-- expected result
    

    这段代码只是我对上面@AMieres 建议的实现。

    【讨论】:

    • 非常好。仅一条评论,我看到您将函数参数命名为functor。实际上,类型BinTree和函数copyAndMapInOrder共同组成了一个函子。函子是一个泛型类型和一个映射函数。
    • @AMieres 感谢您的更正,在这种情况下,映射函数的更好名称是什么?
    • 因为它只是一个简单的函数,我通常称之为f
    猜你喜欢
    • 1970-01-01
    • 2015-01-19
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2016-07-17
    • 2021-09-16
    • 2020-07-16
    相关资源
    最近更新 更多