Functional programming 在OCaml中实现就地图BFS时出现奇怪的错误
我正在OCaml中实现Functional programming 在OCaml中实现就地图BFS时出现奇怪的错误,functional-programming,ocaml,Functional Programming,Ocaml,我正在OCaml中实现就地图形BFS 这是我的密码: type graph = {s : int list array;num_v:int;mutable num_e : int};; let bfs u g p = let marker = Array.make g.num_v false in let q = Queue.create() in Queue.push u q; let rec add_to_queue v = function | [] -
就地图形BFS
这是我的密码:
type graph = {s : int list array;num_v:int;mutable num_e : int};;
let bfs u g p =
let marker = Array.make g.num_v false
in
let q = Queue.create()
in
Queue.push u q;
let rec add_to_queue v = function
| [] -> ()
| hd::tl ->
if not marker.(hd) then begin
marker.(hd) <- true;
Queue.push hd q;
p.(hd) <- v
end;
add_to_queue v tl
in
**let rec bfs_go =**
if Queue.length q > 0 then begin
let v = Queue.pop q
in
print_int v;
add_to_queue v g.s.(v);
bfs_go
end
in
bfs_go;;
你可能是说
let rec bfs_go () =
...;
bfs_go ()
而不是
let rec bfs_go =
...;
bfs_go
编辑:我无法抗拒一些改进
你的命令式风格:
let bfs start graph from =
let marker = Array.make graph.num_v false in
let q = Queue.create() in
let add_to_queue parent node =
if not marker.(node) then begin
marker.(node) <- true;
Queue.push node q;
from.(node) <- parent;
end in
Queue.push start q;
while not (Queue.is_empty q) do
let node = Queue.pop q in
print_int node;
List.iter (add_to_queue node) graph.s.(node)
done
让bfs从=
让marker=Array.make graph.num\u v在中为false
让q=队列中的Queue.create()
让我们将\u添加到\u队列父节点=
如果不是标记。(节点),则开始
标记。(节点)bfs next[]
|节点::当前,下一个->
让我们接下来添加父节点=
如果是标记。(节点),则为下一步
否则开始
标记(节点)
打印节点;
让孩子=
中的List.filter(趣味儿童->非标记(儿童))g.s.(节点)
iter(有趣的孩子->标记器(孩子)你可能是指
let rec bfs_go () =
...;
bfs_go ()
而不是
let rec bfs_go =
...;
bfs_go
编辑:我无法抗拒一些改进
你的命令式风格:
let bfs start graph from =
let marker = Array.make graph.num_v false in
let q = Queue.create() in
let add_to_queue parent node =
if not marker.(node) then begin
marker.(node) <- true;
Queue.push node q;
from.(node) <- parent;
end in
Queue.push start q;
while not (Queue.is_empty q) do
let node = Queue.pop q in
print_int node;
List.iter (add_to_queue node) graph.s.(node)
done
让bfs从=
让marker=Array.make graph.num\u v在中为false
让q=队列中的Queue.create()
让我们将\u添加到\u队列父节点=
如果不是标记。(节点),则开始
标记。(节点)bfs next[]
|节点::当前,下一个->
让我们接下来添加父节点=
如果是标记。(节点),则为下一步
否则开始
标记(节点)
打印节点;
让孩子=
中的List.filter(趣味儿童->非标记(儿童))g.s.(节点)
顺便问一下,我真的应该为OCaml/FPL使用循环吗?@JacksonTale当它们导致简洁优雅的代码时,你应该使用它。在这种情况下,我认为递归对而没有任何好处。在一般情况下,循环的问题是它们迫使你使用副作用(通常是坏的)在您的实现中,我是否可以将您的[],(\u::\ uAS next)->bfs next[]
更改为[],next->bfs next[]
?此外,我使用的任何差异都是列表。左折
而不是列表。右折
?左折
和右折
将以不同的顺序累积值,遍历仍将是BFS,但相同级别的节点以不同的顺序遍历。事实上,我使用两个列表而不是一个队列的方式,没有反转next
意味着我已经更改了与您的代码相关的顺序,因此列表。向左折叠实际上会更好。关于(::uu作为next)
,我个人更喜欢它,因为它使模式不重叠,因此通过重新排序得以保留;在代码中,如果您切换前两个子句,它会改变语义。但这也是一个合理的选择。顺便问一下,我真的应该为OCaml/FPL使用loop吗?@JacksonTale当它们导致简洁优雅的代码时,您应该这样做在一般情况下,循环的问题是它们迫使你使用副作用(通常是不好的),但在这里你还是有副作用的,所以没有什么理由不这样做。在你的实现中,我可以把你的[],(::u.as next)->bfs next[]改成[],next->bfs next[]
?此外,我使用的任何差异都是列表。左折
而不是列表。右折
?左折
和右折
将以不同的顺序累积值,遍历仍将是BFS,但相同级别的节点以不同的顺序遍历。事实上,我使用两个列表而不是一个队列的方式,没有反转next
意味着我已经更改了与您的代码相关的顺序,因此列表。向左折叠实际上会更好。关于(::uu作为next)
,我个人更喜欢它,因为它使模式不重叠,因此可以通过重新排序来保留;在代码中,如果切换前两个子句,它会改变语义。但这也是一个合理的选择。
let dfs u g p =
let marker = Array.make g.num_v false in
let rec dfs_go node =
print_int node;
let go_child child =
if not marker.(child) then begin
marker.(child) <- true;
dfs_go child;
end in
List.iter go_child g.s.(node)
in
marker.(u) <- true;
dfs_go u;;