Algorithm 从左到右枚举无限树的递归

Algorithm 从左到右枚举无限树的递归,algorithm,recursion,tree,f#,purely-functional,Algorithm,Recursion,Tree,F#,Purely Functional,我有一棵树,由 type LazyTree<'T> = | LazyBranch of 'T * ('T LazyTree list Lazy) 分配这样的数字是不可能的,因为它需要对无限树进行非惰性遍历。 您需要的是广度优先遍历,如以下伪代码所示: let traverse (node:LazyTree<'T>) = let q = System.Collections.Generic.Queue() q.Enqueue node

我有一棵树,由

type LazyTree<'T> =
    | LazyBranch of 'T * ('T LazyTree list Lazy) 

分配这样的数字是不可能的,因为它需要对无限树进行非惰性遍历。 您需要的是广度优先遍历,如以下伪代码所示:

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

您是对的,这里需要的递归结构有些复杂。这里有一种方法。我将使用一个助手函数number,它为一个树列表编号,给定前面的编号树以及该列表和列表中第一棵树的第一个子树之间的所有编号树。然后,如果列表非空:

可以递归地计算所需列表的尾部,传入将列表头部编号为上一棵树的待计算结果,并将该列表的子元素附加到中间列表,因为它们位于第二个元素的子元素之前。 与列表头相对应的编号树只取其前一个编号后的下一个编号作为其值。该节点的子节点也可以递归计算。考虑所有的编号树之间对应的头和它的孩子;这与现有的中间序列稍有不同,中间序列中的元素仅从该列表的尾部开始,因此我们需要将在步骤1中计算的列表的尾部附加到现有中间序列的前面。如果有这样一个节点,则头节点的第一个子节点之前的节点只是这个新中间序列的最后一个元素,如果没有,则是编号树本身。如果节点及其子节点之间没有节点,则可能发生这种情况。子节点和它们的第一个子节点之间的节点就是这个新中间序列的子节点。 很抱歉,如果这个描述没有启发性,但是画一幅画可能会有所帮助。无论如何,下面是相应的代码:

// 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

你想出了什么解决方案?它们有什么副作用?我想出了一个有限树的解决方案。我只是将其作为列表遍历,然后从该列表中恢复树结构。不会在那里工作的。我没有试着用副作用来解决它。如果你投票决定关闭,请在评论中告诉我,如果你能解决它,至少不用提出解决方案。我想我能解决它,但不能用递归。我在写think,因为现在还不清楚你到底想实现什么。从一个角度看,您以分层的方式为节点分配数字,从另一个角度看,您告诉我们函数应该返回一个树,而没有解释您期望的树是什么。感谢您注意到我的正式描述中的错误。我纠正了它。我仍然认为,这个问题确实属于这个网站。我可以在纸上懒洋洋地生成这样的树,所以可以编程。这段代码不生成任何树,因此它是无关的。此外,还可以用惰性代码替换它:
// 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