【发布时间】:2015-08-29 06:59:38
【问题描述】:
我正在研究 Ocaml,但我还是个初学者,所以我必须寻求一些帮助。
按照书上的说明,我创建了一个表示有向图的类型:
type 'a graph = Gr of ('a * 'a) list;;
let grafo1 = Gr [(1,2);(1,3);(1,4);(2,6);(3,5);(4,6);(6,5);(6,7);(5,4)];;
然后我创建了一个以节点为输入的 succ 函数,它给我他的继任者作为输出:
let succ (Gr arcs) n=
let rec aux = function
[] -> []
| (x,y):: rest ->
if n = x then y::(aux rest)
else aux rest
in aux arcs;;
然后我用 succ 函数做了一个修改后的 BFS 函数,这个函数告诉我是否存在 2 个节点之间的路径:
let bfs graph p start =
let rec search visited = function
[] -> raise Nodo_not_reachable
|n:: rest ->
if List.mem n visited
then search visited rest
else if p n then n
else search (n::visited) (rest @ (succ graph n))
in search [] [start];;
我使用以下代码调用函数:
bfs grafo1 (function x -> x=7) 1;;
如果节点 1 和节点 7 之间存在路径,则函数将输出 true。 现在,我想做同样的事情,但使用加权图,所以我创建了一个新类型,一个列表,其中每个元素由 3 个数字而不是 2 个数字组成:(节点开始 - 边缘的 wiegh - 节点到达):
type 'b graph_w = Grw of ('b * 'b * 'b) list;;
let grafo2 = Grw [(1,3,2);(1,1,5);(2,2,3);(5,5,3);(5,4,6);(3,1,6);(3,7,4);(6,2,7);(4,4,6)];;
所以,我修改了我之前的函数以适应这种类型:
let succ_w (Grw arcs) n=
let rec aux = function
[]-> []
| (x,y,z)::rest ->
if n=x then z::(aux rest)
else aux rest
in aux arcs;;
let bfs_w graph_w p start =
let rec search visited = function
[] -> raise Nodo_non_raggiungibile
|n:: rest ->
if find n visited
then search visited rest
else if p n then n
else search (n::visited) (rest @ (succ_w graph_w n))
in search [] [start];;
(因为我不能在这种新类型上使用 List.mem,所以我声明了一个名为 find 的函数,如果元素 (x,y,z) 包含在列表中,则输出为 true):
let rec find (x,y,z) = function
[] -> false
| (v,c,p)::rest -> if (x=v) then true else find (x,y,z) rest;;
find (2,3,1) [(2,2,3);(4,5,6);(8,9,0)];;
现在有个小问题,谁能告诉我如何使用新的图形类型调用我的 bfs_w 函数?
使用
bfs_w grafo2 (function x -> x=7) 1;;
我收到以下错误:
This expression has type int graph_w but an expression was expected of type ('a * 'b * 'c) graph_w
/--------------------------------/
好的,现在函数可以正常工作了 thx ^^,但是还有另一个问题:因为我想使用 bfs 解决最长路径问题(给定一个开始节点和一个停止节点,如果节点之间存在路径最小权重 k) 我必须在我的函数上实现 (x,y,z) 格式,所以我尝试了这样的方法:(与您建议的函数相同,但使用 (x,y,z) 代替 n:
let bfs_w2 graph_w start stop =
let rec search visited = function
| [] -> raise Node_not_Reachable
| (v,c,p) :: rest ->
if (find (v,c,p) visited) then search visited rest
else if v = stop then true
else search ((v,c,p)::visited) (rest @ (succ_w graph_w (v,c,p))) in
search [] [start];;
当我声明函数时:
bfs_w2 grafo2 1 4;;
或
bfs_w2 grafo2 (function x -> x=4) 1;;
我在“grafo2”上遇到了同样的错误:
This expression has type int graph_w
但表达式应为 ('a * 'b * 'c) graph_w 类型
我不明白问题出在哪里,功能与您建议的几乎相同。
ps:我什至试过这个,但我遇到了同样的结果:
let bfs_w2 graph_w p start =
let rec search visited = function
| [] -> raise Nodo_not_reachable
| (x,y,z) :: rest ->
if (List.mem (x,y,z) visited) then search visited rest
else if p (x,y,z) then (x,y,z)
else search ((x,y,z)::visited) (rest @ (succ_w graph_w (x,y,z))) in
search [] [start];;
【问题讨论】: