使用Union-Find获取等价类

时间:2015-03-25 09:07:21

标签: ocaml

我有一个简单的union-find代码,如下所示:

let rec find p x =
      if p.(x) = x
      then x
      else
        let y = find p (p.(x)) in
        p.(x) <- y;
        y;;       
let union x y p =
  p.(find p y) <- p.(find p x);
  p

示例:

let a = [|0;1;2;3;4|]

let print_array a =
 Array.iter (fun i -> Printf.printf "%i" i; print_string " ") a

let print_union =
  let a = union 0 1 a in
  print_string "Result union (0, 1): ";
  print_array a;
  print_string "\n"

结果将是:

Result union (0, 1): 0 0 2 3 4 

我很难进一步得到不相交的东西。 例如,上面的示例我想得到:{0,1},{2},{3},{4}

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

由于显而易见的原因,您无法通过整个结构打印该结果。

所以,你想收集所有工会的居民 - 发现:

let print_classes a =
 (* Let's first create an array for storing the classes *)
 let classes = Array.make (Array.length a) [] in

 (* Let's now populate it!
    I'm going backwards in the array to have nicer printing *)
 for i = (Array.length classes) - 1 downto 0
 do classes.(a.(i)) <- i :: (classes.(a.(i))) done;

 (* And now the printing *)
 Array.iter (function
   | [] -> ()
   | h::t -> Printf.printf "{%d%a}" h
             (fun c -> List.iter (fun x -> Printf.fprintf c ",%i" x)) t
   )
   classes

为了简洁起见,我使用了Printf功能,你可以找到他们的文档here

请注意,这可能会有所改进,因为它会创建一个可能很大的数组,而且几乎不会#34;填充。根据您使用此功能的频率,您可能希望将等价类与类别负责人一起存储(我必须这样做一次,我使用了SetMap来自stdlib)。