优雅的BFS在ocaml

时间:2017-04-02 15:15:25

标签: algorithm ocaml graph-theory breadth-first-search

我想修复我的bfs函数,问题是当它接收到不存在的节点时,它也将它们打印为访问过的。

此功能已经非常庞大,因此添加了一个支票:

if node not in graph then ...也会使我的功能更加膨胀,我想避免使用它,因为我希望看到一个“眼睛可调试”的更短的功能。

此外,我选择了Hashtable,因为与Set

相对
  1. 这是可变的
  2. 这是一个数组,但Set是一个平衡的二叉树
  3. (如果您的个人喜好与Set一致,请告诉我原因)

        type 'a graph = Gr of ('a * 'a list) list
    
        let get_neighbors node (Gr g) = 
            try List.assoc node g with Not_found -> []
    
        let bfs start g = 
            let v = Hashtbl.create 100 in (*ideally it should be the # of distinct nodes*)
            let q = Queue.create () in    (*v is for visited nodes*)
    
            let rec bfs' cur_n acc = 
                    get_neighbors cur_n g |>
                    List.iter
                    (fun n -> 
                        try Hashtbl.find v n
                        with Not_found -> 
                            Hashtbl.add v n ();
                            Queue.push n q);
                    Hashtbl.add v cur_n (); 
                    try bfs' (Queue.pop q) (cur_n::acc)
                    with Queue.Empty -> List.rev (cur_n::acc) in
                    bfs' start []
    

    示例:

        let g =  
            Gr [
                 ('a', ['e'; 'b'; 'c']); 
                 ('b', ['e'; 'd']); 
                 ('e', ['d'; 'f']);
                 ('g', ['t';'s'])
               ]
    
        # bfs 'a' g;;
        - : char list = ['a'; 'e'; 'b'; 'c'; 'd'; 'f']
        # bfs 'z' g;;
        - : char list = ['z'] (*doesn't make sense, g doesn't have 'z' node*)
    

1 个答案:

答案 0 :(得分:2)

在我看来,Not_found中的get_neighbors异常表示不存在的节点。但是你的代码正在处理这种情况,如果它表明没有后继者的节点。

如果您的图表结构良好,则邻居列表不应包含任何不存在的节点。因此,此节点可以来自的唯一位置是初始调用。

所以我会将这个Not_found异常的处理移到最外层。