mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 11:15:31 -05:00
85 lines
3.3 KiB
OCaml
85 lines
3.3 KiB
OCaml
(*
|
|
Copyright (c) 2013, Simon Cruanes
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
Redistributions of source code must retain the above copyright notice, this
|
|
list of conditions and the following disclaimer. Redistributions in binary
|
|
form must reproduce the above copyright notice, this list of conditions and the
|
|
following disclaimer in the documentation and/or other materials provided with
|
|
the distribution.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*)
|
|
|
|
(** {1 Imperative Union-Find structure} *)
|
|
|
|
(** This structure operates on arbitrary objects as long as they are
|
|
hashable. It maps keys to values (values belong to a monoid,
|
|
if they are not needed, unit makes for a simple implementation)
|
|
and each equivalence class' representative maps to
|
|
the monoid merge of all the class' elements values.
|
|
One also can iterate on the representative elements. *)
|
|
|
|
(** We need to be able to hash and compare keys, and values need to form
|
|
a monoid *)
|
|
module type PAIR = sig
|
|
type key
|
|
type value
|
|
|
|
val hash : key -> int
|
|
val equal : key -> key -> bool
|
|
|
|
val merge : value -> value -> value (** Should be associative commutative *)
|
|
val zero : value (** Neutral element of {!merge} *)
|
|
end
|
|
|
|
(** Build a union-find module from a key/value specification *)
|
|
module Make(P : PAIR) : sig
|
|
type key = P.key
|
|
(** Elements that can be compared *)
|
|
|
|
type value = P.value
|
|
(** Values associated with elements *)
|
|
|
|
type t
|
|
(** The union-find imperative structure itself *)
|
|
|
|
val create : key list -> t
|
|
(** Create a union-find for the given elements. Elements are mapped
|
|
to zero by default. *)
|
|
|
|
val mem : t -> key -> bool
|
|
(** Does the key belong to the UF? *)
|
|
|
|
val find : t -> key -> key
|
|
(** Finds the representative of this key's equivalence class.
|
|
@raise Not_found if the key does not belong to the UF *)
|
|
|
|
val find_value : t -> key -> value
|
|
(** Find value for the given element. The value is the monoid
|
|
merge of all values associated to [key]'s equivalence class.
|
|
@raise Not_found if [mem uf key] is false. *)
|
|
|
|
val union : t -> key -> key -> unit
|
|
(** Merge two elements (and their equivalence classes) *)
|
|
|
|
val add : t -> key -> value -> unit
|
|
(** Add the given value to the key's class (monoid). It modifies the value
|
|
by merging it with [value]. If the key does not belong
|
|
to the union-find, it is added. *)
|
|
|
|
val iter : t -> (key -> value -> unit) -> unit
|
|
(** Iterate on representative and their value *)
|
|
end
|