如何解决将无限树转换为无限流
问题描述
我有一个懒惰的无限二叉树:
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,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 为根的树将具有以 5 和 6 开头的流。所以这个子树转换为流 3,6 ...
另一个子树变为 {{1}所以整体结果流将是
2,3 ...
我们可以通过维护队列来管理树中节点的访问顺序。
问题
我的问题是,有没有更简单的方法?我们可以不使用队列而只使用递归来获得所需的顺序吗?
解决方法
试图摆脱尾递归版本是不寻常的,但是是的,您可以在调用堆栈中隐藏广度优先遍历的队列。例如,您可以定义一个交错函数,以降低的频率切换左右源:
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))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。