递归以从左到右枚举无限树

时间:2016-06-24 05:20:26

标签: algorithm recursion tree f# purely-functional

我有一个由

代表的树
type LazyTree<'T> =
    | LazyBranch of 'T * ('T LazyTree list Lazy) 

我想为每个节点分配一个数字n,从左到右计数。

更正式

编辑:

对于节点a,如果h(a)=0没有子节点,则a

对于父ap

的节点h(a)=h(p+1)

对于没有父级的节点aL(a)是空集。

对于具有父级的节点aL(a)是一组所有节点,对于每个节点i,从根到它的路径不包含{ {1}}

对于节点aaS(a)的所有元素,其中每个元素L(a)都包含i

我需要将每个节点h(i)<=h(a)的值替换为a

的大小

enter image description here

我不能为我的问题找到一个不涉及副作用的解决方案。

我的功能应该返回一棵树。

它的节点依赖于左兄弟节点。因此,该函数应该以{{1​​}}作为参数。

但它最左边的孩子依赖于我们最右边的兄弟姐妹,这依赖于我们。看来,我们有一个无限循环。

我不会问如何在有限树上解决它。

我不是在问一个抽象的概念。 以下是如何从另一个树中返回一个无限树:

S(a)

2 个答案:

答案 0 :(得分:1)

你说这里所需的递归结构有点错综复杂。这是一种方法。我将使用辅助函数number,该函数对给定前一个编号树的树列表以及此列表与此列表中第一个树的第一个子树之间的所有编号树进行编号。然后,如果列表非空:

  1. 可以递归地计算所需列表的尾部,传递将列表头部编号为前一树的待计算结果,并将该列表的子项附加到“中间”列表中因为他们来到第二个元素的孩子面前。
  2. 对应于列表头部的编号树只取其前一个后面的下一个数字作为其值。也可以递归地计算该节点的子节点。考虑与头部及其子项相对应的编号树的所有;这与现有的中间序列略有不同,后者只有在此列表的尾部之后开始的元素,因此我们需要将在步骤1中计算的列表的尾部附加在现有的“中间”列表之前。然后,如果存在这样的节点,紧接在头节点的第一个子节点之前的节点就是这个新的中间序列的最后一个元素,如果不存在,则编号的树本身就是这个节点(如果在节点之间没有节点,则可能发生这种情况)节点及其子节点)。孩子们和他们的第一个孩子之间的节点就是这个新的中间序列的孩子。
  3. 很抱歉,如果此说明没有启发性,但绘制图片可能有所帮助。无论如何,这是相应的代码:

    // These help with type inference
    let value (LazyBranch(v,_)) = v
    let children (LazyBranch(_,ts)) = ts.Value
    
    let numberedTree =
        let rec number prev between = function
        | [] -> []
        | t::ts ->
            let rec rest = number first (seq { yield! between; yield! children first }) ts
            and first =
                let between' = seq { yield! rest; yield! between }
                LazyBranch(value prev + 1, lazy (children t |> number (defaultArg (Seq.tryLast between') first) (between' |> Seq.collect children)))
            first::rest
        fun t ->
            let rec result = LazyBranch(0, lazy number result [] (children t))
            result
    

答案 1 :(得分:-2)

分配这样的数字是不可能的,因为它需要(非懒惰)遍历无限树。 你需要的是广度优先遍历,就像在这个伪代码中一样:

let traverse (node:LazyTree<'T>) =
     let q = System.Collections.Generic.Queue()
     q.Enqueue node
     let mutable i = 0
     while 0 < q.Count do // always TRUE
        let node = q.Dequeue ()
        printfn "Node #%i: %A" i node.Map
        i <- i + 1
        for child in node.Children.Force() do
            q.Enqueue child