【问题标题】:F# tree leaves to list with continuation tail-recursionF# 树的叶子以连续尾递归列出
【发布时间】:2018-11-10 12:43:48
【问题描述】:

我有一棵有树枝和树叶的类型树。我想得到一个叶子值列表。到目前为止,我只能数树枝。

我的树:

type 'a tr =
  | Leaf   of 'a
  | Branch of 'a tr * 'a tr

还有我的代码:

let getList (tr:float tr)=
    let rec toList tree acc =
        match tree with
        | Leaf _ -> acc 0
        | Branch (tl,tr) -> toList tl (fun vl -> toList tr (fun vr -> acc(vl+vr+1)))
    toList tr id     

输入:

 let test=Branch (Leaf 1.2, Branch(Leaf 1.2, Branch(Branch(Leaf 4.5, Leaf 6.6), Leaf 5.4)))
 getList test

因此,我想得到一个列表:

[1.2; 1.2; 4.5; 6.6; 5.4]

我尝试了一些类似的变体,但没有成功。

  | Branch (tl,tr) -> toList tl (fun vl -> toList tr (fun vr -> (vl::vr)::acc))
    toList tr [] 

任何帮助将不胜感激。

【问题讨论】:

    标签: list f# tree tail-recursion


    【解决方案1】:

    这是由于您的延续函数 (acc) 的签名是 (int -> 'a) 如果你想得到一个扁平化列表,延续函数签名应该是 ('a list -> 'b)

    let getList tree =
        let rec toList tree cont =
            match tree with
            | Leaf a -> cont [a]
            | Branch (left, right) -> 
                toList left (fun l -> 
                    toList right (fun r -> 
                        cont (l @ r)))
        toList tree id
    

    编辑;这应该更有效

    let getList tree = 
        let rec toList tree cont acc =
            match tree with 
            | Leaf a               -> cont (a :: acc)
            | Branch (left, right) -> toList left (toList right cont) acc
        toList tree id [] |> List.rev
    

    【讨论】:

      【解决方案2】:

      请注意,您的树类型不能表示只有一个子节点的节点。类型应该是:

      type Tree<'T> =
          | Leaf of 'T
          | OnlyOne of Tree<'T>
          | Both of Tree<'T> * Tree<'T>
      

      要使用尾递归和延续,请使用延续函数,而不是accumulator:

      let leaves tree =
          let rec collect tree cont =
              match tree with
              | Leaf x -> cont [x]
              | OnlyOne tree -> collect tree cont
              | Both (leftTree, rightTree) ->
                  collect leftTree (fun leftAcc ->
                      collect rightTree (fun rightAcc ->
                          leftAcc @ rightAcc |> cont))
          collect tree id
      

      P/S:你的命名不太好:tr含义太多。

      【讨论】:

        猜你喜欢
        • 2015-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多