【问题标题】:Convert an infinite tree into an infinite stream将无限树转换为无限流
【发布时间】:2021-04-07 16:32:09
【问题描述】:

问题描述

我有一棵惰性无限二叉树:

type 'a tree_node = TN of 'a * 'a inf_btree * 'a inf_btree
  and 'a inf_btree = 'a tree_node Lazy.t 

let rec ibt_map (f : 'a -> 'b) (t : 'a inf_btree) : 'b inf_btree = 
  let TN (x, ltree, rtree) = Lazy.force t in 
  lazy (TN (f x, ibt_map f ltree, ibt_map f rtree))

let rec example : int inf_btree = 
  lazy (TN (1, 
              ibt_map ((+) 1) example, 
              ibt_map ((+) 2) example
           )
       ) 
;;

还有一个惰性流:

type 'a link_node = LN of 'a * 'a stream 
  and 'a stream = 'a link_node Lazy.t

现在我想将树转换为流,以保持树中元素的顺序。更准确地说,我希望靠近根的元素在流的早期出现。但是,如果它是深度优先的,那么一半的树将永远不会出现在流中:

let df_tree_to_stream (t : 'a inf_btree) : 'a stream = 
  let TN (x, ltree, rtree) = Lazy.force t in 
  let substream1 = df_tree_to_stream ltree in 
  let substream2 = df_tree_to_stream rtree in 
  lazy (LN (x, substream1)) 
  (* how to work in substream2 ??? *)

一种尝试的交替解决方案

我们可以尝试合并两个流,使它们交替出现,但是元素的顺序将不会被保留。在给定的示例中,树看起来像

       1
    3    2
   5 6  4 3
  .........

流的顺序应该是

1, 3, 2, 5, 6, 4, 3, ...

但是如果我们简单地交替子树返回的流,那么以 3 为根的树就会有以 5 和 6 开头的流。所以这个子树转换为流3, 5, 6 ... 另一个子树变成2, 4, 3 ... 所以整体结果流将是

1, 3, 2, 5, 4, ...

我们可以通过维护队列来管理树中节点的访问顺序。


问题

我的问题是,有没有更简单的方法?我们可以不使用队列而仅使用递归来获得所需的顺序吗?

【问题讨论】:

    标签: ocaml lazy-sequences


    【解决方案1】:

    尝试摆脱尾递归版本是不寻常的,但是是的,您可以将广度优先遍历的队列隐藏在调用堆栈中。例如,您可以定义一个交错函数,以递减的频率切换左右源:

    
    let rec interleave first period count l r () =
      if count = 0 then
        if first then
          interleave false period period r l ()
        else
          let period = 2 * period in
          interleave true period period r l ()
      else
        match l () with
        | Seq.Nil -> r ()
        | Seq.Cons(y,l) ->
          Seq.Cons(y, interleave first period (count-1) l r)
    
    let interleave = interleave true 1 1
    
    let rec to_seq tree () =
      let lazy (TN(x,l,r)) = tree in
      Seq.Cons(x, interleave (to_seq l) (to_seq r))
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-11
      • 1970-01-01
      • 2019-03-25
      • 1970-01-01
      • 2020-08-27
      • 2014-05-09
      • 2015-09-25
      相关资源
      最近更新 更多