如何在OCaml中编写BST的迭代顺序遍历
在OCaml中编写递归有序遍历非常容易,但是如何编写迭代遍历呢?使用如何在OCaml中编写BST的迭代顺序遍历,ocaml,binary-search-tree,Ocaml,Binary Search Tree,在OCaml中编写递归有序遍历非常容易,但是如何编写迭代遍历呢?使用for loop或while?要求某人编写一些没有递归调用的东西是愚蠢的,但我仍然会这样做,因为这是一个有趣的练习。从递归到迭代总是同一个过程 type tree = Leaf | Node of int * tree * tree let rec in_order = function | Leaf -> [] | Node(i,l,r) -> in_order l @ (i :: in_order r)
for loop
或while
?要求某人编写一些没有递归调用的东西是愚蠢的,但我仍然会这样做,因为这是一个有趣的练习。从递归到迭代总是同一个过程
type tree = Leaf | Node of int * tree * tree
let rec in_order = function
| Leaf -> []
| Node(i,l,r) -> in_order l @ (i :: in_order r);;
好了,现在我们有了递归函数。第一步是将其转换为尾部递归。这实际上是最困难的一步,因为它需要真正的逻辑和算法更改
我们将向包含计算结果的函数添加一个新参数:
let rec ino res = function
| Leaf -> ()
| Node(i,l,r) ->
begin
ino res r ;
res := i :: !res ;
ino res l
end
最后,结果是!res
现在我们有了这个,删除递归调用非常容易,我们只需要考虑当编译器有一个递归调用时会做什么。在将函数的参数和下一步要做的工作放入堆栈之后,它只执行一个while循环。我们就这么做吧
open Stack
type work = Value of int | NextNode of tree ref
let ino t : int list =
let res = ref [] in
let stack = Stack.create () in
push (NextNode (ref t)) stack;
try
while true do
let current = pop stack in
match current with
Value i -> res := i :: !res
| NextNode n ->
begin
match !n with
Leaf -> ()
| Node(i,l,r) ->
begin
push (NextNode (ref l)) stack;
push (Value i) stack;
push (NextNode (ref r)) stack
end
end
done;
assert false
with
| Empty -> !res
在这里,我们只需记住下一步要做的事情。我们知道,当我们到达一个节点时,我们必须先处理它的右子节点,然后是节点的值,然后是它的左子节点,所以我们只需将所有这些放在堆栈中(当然顺序相反),然后继续处理堆栈的下一个元素。当堆栈为空时,我们已经访问了整棵树,可以返回
我希望这篇文章能够让一些人相信递归比迭代编程更强大。3线对26线。QED。要求某人编写一些没有递归调用的东西是愚蠢的,但我仍然会这样做,因为这是一个有趣的练习。从递归到迭代总是同一个过程
type tree = Leaf | Node of int * tree * tree
let rec in_order = function
| Leaf -> []
| Node(i,l,r) -> in_order l @ (i :: in_order r);;
好了,现在我们有了递归函数。第一步是将其转换为尾部递归。这实际上是最困难的一步,因为它需要真正的逻辑和算法更改
我们将向包含计算结果的函数添加一个新参数:
let rec ino res = function
| Leaf -> ()
| Node(i,l,r) ->
begin
ino res r ;
res := i :: !res ;
ino res l
end
最后,结果是!res
现在我们有了这个,删除递归调用非常容易,我们只需要考虑当编译器有一个递归调用时会做什么。在将函数的参数和下一步要做的工作放入堆栈之后,它只执行一个while循环。我们就这么做吧
open Stack
type work = Value of int | NextNode of tree ref
let ino t : int list =
let res = ref [] in
let stack = Stack.create () in
push (NextNode (ref t)) stack;
try
while true do
let current = pop stack in
match current with
Value i -> res := i :: !res
| NextNode n ->
begin
match !n with
Leaf -> ()
| Node(i,l,r) ->
begin
push (NextNode (ref l)) stack;
push (Value i) stack;
push (NextNode (ref r)) stack
end
end
done;
assert false
with
| Empty -> !res
在这里,我们只需记住下一步要做的事情。我们知道,当我们到达一个节点时,我们必须先处理它的右子节点,然后是节点的值,然后是它的左子节点,所以我们只需将所有这些放在堆栈中(当然顺序相反),然后继续处理堆栈的下一个元素。当堆栈为空时,我们已经访问了整棵树,可以返回
我希望这篇文章能够让一些人相信递归比迭代编程更强大。3线对26线。QED.这里是迭代顺序遍历的另一种方式:
type 'a node = {mutable data: 'a;
mutable left : 'a node option;
mutable right: 'a node option; }
let new_node data = {data; left = None; right = None;}
let insert tree new_data =
let module Wrapper = struct exception Stop_loop end in
let iter = ref tree in
try
while true do
if new_data < !iter.data
then match !iter.left with
| None ->
!iter.left <- Some (new_node new_data);
raise Wrapper.Stop_loop
| Some left_tree -> iter := left_tree
else if new_data > !iter.data
then match !iter.right with
| None ->
!iter.right <- Some (new_node new_data);
raise Wrapper.Stop_loop
| Some right_tree -> iter := right_tree
done
with Wrapper.Stop_loop -> ()
let in_order_traversal tree =
let module W = struct exception Stop_loop end in
let visited_stack = Stack.create () in
let iter_node = ref (Some tree) in
try while true do
(* Inner loop, we keep trying to go left *)
(try while true do
match !iter_node with
| None -> raise W.Stop_loop
| Some left ->
Stack.push left visited_stack;
iter_node := left.left
done;
with W.Stop_loop -> ());
(* If we have no more to process in the stack, then we're
done *)
if Stack.length visited_stack = 0
then raise W.Stop_loop
else
(* Here we're forced to start moving rightward *)
let temp = Stack.pop visited_stack in
Printf.sprintf "%s " temp.data |> print_string;
iter_node := temp.right
done
with W.Stop_loop -> ()
let () =
let root = new_node "F" in
["B";"G";"A";"D";"I";"C";"E";"H"] |> List.iter (insert root);
in_order_traversal root;
print_newline ();
type'a node={mutable data:'a;
可变左:一个节点选项;
可变右键:'节点选项;}
让新节点数据={data;left=None;right=None;}
让我们插入新的树数据=
让模块包装器=结构异常停止\u循环结束
让iter=ref树进入
尝试
尽管如此
如果有新数据<!国际热核实验堆数据
然后比赛!国际热核聚变实验堆
|无->
!iter.left iter:=左树
否则,如果新数据>!国际热核实验堆数据
然后比赛!国际热核聚变实验堆
|无->
!iter.right iter:=右树
完成
使用Wrapper.Stop_循环->()
让我们按顺序遍历树=
让模块W=struct exception Stop\u循环结束
让我们在中访问\u stack=stack.create()
让iter_node=ref(某棵树)进入
千方百计
(*内循环,我们一直尝试向左*)
(千方百计
匹配!iter_节点与
|无->上升带停止循环
|一些人离开了->
Stack.push left\u Stack;
iter_节点:=left.left
完成;
使用W.Stop_loop->());
(*如果堆栈中没有更多要处理的内容,则
完成*)
如果Stack.length\u Stack=0
然后升起W停止循环
其他的
(*这里我们被迫开始向右移动*)
让temp=Stack.pop\u Stack in
Printf.sprintf“%s”临时数据|>print_字符串;
iter_节点:=右侧温度
完成
带W.Stop_循环->()
让()=
设root=in中的新_节点“F”
[“B”;“G”;“A”;“D”;“I”;“C”;“E”;“H”]|>List.iter(插入根);
按顺序遍历根;
打印新行();
下面是迭代顺序遍历的另一种方式:
type 'a node = {mutable data: 'a;
mutable left : 'a node option;
mutable right: 'a node option; }
let new_node data = {data; left = None; right = None;}
let insert tree new_data =
let module Wrapper = struct exception Stop_loop end in
let iter = ref tree in
try
while true do
if new_data < !iter.data
then match !iter.left with
| None ->
!iter.left <- Some (new_node new_data);
raise Wrapper.Stop_loop
| Some left_tree -> iter := left_tree
else if new_data > !iter.data
then match !iter.right with
| None ->
!iter.right <- Some (new_node new_data);
raise Wrapper.Stop_loop
| Some right_tree -> iter := right_tree
done
with Wrapper.Stop_loop -> ()
let in_order_traversal tree =
let module W = struct exception Stop_loop end in
let visited_stack = Stack.create () in
let iter_node = ref (Some tree) in
try while true do
(* Inner loop, we keep trying to go left *)
(try while true do
match !iter_node with
| None -> raise W.Stop_loop
| Some left ->
Stack.push left visited_stack;
iter_node := left.left
done;
with W.Stop_loop -> ());
(* If we have no more to process in the stack, then we're
done *)
if Stack.length visited_stack = 0
then raise W.Stop_loop
else
(* Here we're forced to start moving rightward *)
let temp = Stack.pop visited_stack in
Printf.sprintf "%s " temp.data |> print_string;
iter_node := temp.right
done
with W.Stop_loop -> ()
let () =
let root = new_node "F" in
["B";"G";"A";"D";"I";"C";"E";"H"] |> List.iter (insert root);
in_order_traversal root;
print_newline ();
type'a node={mutable data:'a;
可变左:一个节点选项;
可变右键:'节点选项;}
让新节点数据={data;left=None;right=None;}
让我们插入新的树数据=
让模块包装器=结构异常停止\u循环结束
让iter=ref树进入
尝试
尽管如此
如果有新数据<!国际热核实验堆数据
然后比赛!国际热核聚变实验堆
|无->
!iter.left iter:=左树
否则,如果新数据>!国际热核实验堆数据
然后比赛!国际热核聚变实验堆
|无->
!iter.right iter:=右树
完成
使用Wrapper.Stop_循环->()
让我们按顺序遍历树=
让模块W=struct exception Stop\u循环结束
让我们在中访问\u stack=stack.create()
让iter_node=ref(某棵树)进入
千方百计
(*内循环,我们一直尝试向左*)
(千方百计
匹配!iter_节点与
|无->上升带停止循环
|一些人离开了->
Stack.push left\u Stack;
iter_节点:=left.left
完成;
使用W.Stop_loop->());
(*如果堆栈中没有更多要处理的内容,则
完成*)
如果Stack.length\u Stack=0
然后升起W停止循环
其他的
(*这里我们被迫开始向右移动*)
设温度=S