我Map
用来实现pure functional
DFS
和BFS
用于图形。
这是我的代码:
module IntMap = Map.Make(struct type t = int let compare = compare end);;
module IntSet = Set.Make(struct type t = int let compare = compare end);;
type digraph = int list IntMap.t;;
exception CantAddEdge;;
let create v =
let rec fill i acc =
if i < v then
fill (i+1) (IntMap.add i [] acc)
else
acc
in
fill 0 IntMap.empty;;
let num_vertices g = IntMap.cardinal g;;
let add_edge u v g =
if IntMap.mem u g && IntMap.mem v g then
let add u v g =
let l = IntMap.find u g in
if List.mem v l then g
else IntMap.add u (v::l) g
in
add u v (add v u g)
else
raise CantAddEdge;;
let dfs_path u g =
let rec dfs current visited path =
let dfs_child current (visited, path) c =
if not (IntSet.mem c visited) then
dfs c (IntSet.add c visited) (IntMap.add c current path)
else
(visited, path)
in
List.fold_left (dfs_child current) (visited, path) (IntMap.find current g)
in
let (v, p) = dfs u (IntSet.singleton u) IntMap.empty
in
p;;
let bfs_path u g =
let rec bfs current_list v p n =
let bfs_current (v,p,n) current =
let bfs_child current (v, p, n) c =
if not (IntSet.mem c v) then begin
print_int c;
((IntSet.add c v), (IntMap.add c current p), (c::n))
end
else
(v, p, n)
in
List.fold_left (bfs_child current) (v, p, n) (IntMap.find current g)
in
let (v,p,n) = List.fold_left bfs_current (v,p,n) current_list
in
if n = [] then p
else bfs n v p []
in
bfs [u] (IntSet.singleton u) IntMap.empty [];;
我知道代码很长,但我真的希望得到一些建议:
- 是否值得真正实现一组纯函数式的图算法?我这样做是因为我现在已经习惯
functional
和讨厌imperative
了。 - 我的实现是否在某些部分或全部方面过于复杂?
- 虽然我喜欢
functional
,但我个人认为我所做的实现似乎比imperative
array-everywhere 版本更复杂。我的感觉对吗?
编辑
添加Bipartite
代码
(* basically, we have two sets, one for red node and the other for black node*)
(* we keep marking color to nodes via DFS and different level of nodes go to coresponding color set*)
(* unless a node is meant to be one color but already in the set of the other color*)
type colorType = Red | Black;;
let dfs_bipartite u g =
let rec dfs current color red black block =
if block then (red, black, block)
else
let dfs_child current color (red, black, block) c =
if block then (red, black, block)
else
let c_red = IntSet.mem c red and c_black = IntSet.mem c black in
if (not c_red) && (not c_black) then
if color = Red then
dfs c Black (IntSet.add c red) black false
else
dfs c Red red (IntSet.add c black) false
else if (c_red && color = Black) || (c_black && color = Red) then (red, black, true)
else (red, black, block)
in
List.fold_left (dfs_child current color) (red, black, block) (IntMap.find current g)
in
let (r, b, block) = dfs u Black (IntSet.singleton u) IntSet.empty false
in
not block;;
编辑 2
具有基于列表的路径的 DFS
let dfs_path u g =
let rec dfs current visited path =
let dfs_child (visited, path) c =
if not (IntSet.mem c visited) then begin
print_int c;
dfs c (IntSet.add c visited) (c::path)
end
else (visited, path)
in
List.fold_left dfs_child (visited, path) (IntMap.find current g)
in
let (v, p) = dfs u (IntSet.singleton u) [u]
in
p;;