mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-06 03:05:28 -05:00
doc/CCHeap: document complexities
Committing to these complexities in documentation is not a constraint for representation of heaps, because they are achieved by every well-known representation (for some of them, in amortized time): https://en.wikipedia.org/wiki/Template:Heap_Running_Times - `find_min`: O(1) - `take`: O(log n) - `insert`: O(log n) - `merge`: O(log(m+n)) (excepted binary heaps which only achieve O(m+n)) - `add_seq`: O(n log(m+n)) (trivially, by repeated insertion) + this can be improved to O(log(m) + n), regardless of the representation of heaps (to be done in a later commit) - `of_seq`: O(n log n) (ditto: can be improved to O(n)) Less trivial: - `filter`, `delete_{one,all}`: + O(n) can be achieved for any reasonable representation of heaps, by using `of_seq` and `to_seq` which, as said, can always be made O(n). + With the current implementation, it is not obvious, but the complexity of `filter` and `delete_all` is Θ(n log n); the complexity of `delete_one` is O(n). Indeed, node rebuilding with `_make_node` is in O(1), merging is in Θ(log n), and every element deletion induces one merge; there are heap instances that achieve the worst case Ω(n log n), for instance: x / \ x y / \ ... y / x / \ h y with n/3 occurrences of x, n/3 occurrences of y, a sub-heap h of n/3 elements, and when y is greater than all elements of h; then, deleting all occurrences of x performs the following computation: merge (merge (merge (merge h y) …) y) y where each `merge` takes time Θ(log n).
This commit is contained in:
parent
8666faf257
commit
793bad1e5b
2 changed files with 60 additions and 22 deletions
|
|
@ -37,37 +37,47 @@ module type S = sig
|
|||
exception Empty
|
||||
|
||||
val merge : t -> t -> t
|
||||
(** Merge two heaps. *)
|
||||
(** [merge h1 h2] merges the two heaps [h1] and [h2].
|
||||
Complexity: [O(log (m+n))] where [m] and [n] are the number of elements in each heap.
|
||||
*)
|
||||
|
||||
val insert : elt -> t -> t
|
||||
(** Insert a value in the heap. *)
|
||||
(** [insert x h] inserts an element [x] into the heap [h].
|
||||
Complexity: [O(log n)] where [n] is the number of elements in [h].
|
||||
*)
|
||||
|
||||
val add : t -> elt -> t
|
||||
(** Synonym to {!insert}. *)
|
||||
(** [add h x] is [insert x h]. *)
|
||||
|
||||
val filter : (elt -> bool) -> t -> t
|
||||
(** Filter values, only retaining the ones that satisfy the predicate.
|
||||
Linear time at least. *)
|
||||
(** [filter p h] filters values, only retaining the ones that satisfy the predicate [p].
|
||||
Complexity: [O(n log n)].
|
||||
*)
|
||||
|
||||
val find_min : t -> elt option
|
||||
(** Find minimal element. *)
|
||||
(** [find_min h] find the minimal element of the heap [h].
|
||||
Complexity: [O(1)].
|
||||
*)
|
||||
|
||||
val find_min_exn : t -> elt
|
||||
(** Like {!find_min} but can fail.
|
||||
(** [find_min_exn h] is like {!find_min} but can fail.
|
||||
@raise Empty if the heap is empty. *)
|
||||
|
||||
val take : t -> (t * elt) option
|
||||
(** Extract and return the minimum element, and the new heap (without
|
||||
this element), or [None] if the heap is empty. *)
|
||||
(** [take h] extracts and returns the minimum element, and the new heap (without
|
||||
this element), or [None] if the heap [h] is empty.
|
||||
Complexity: [O(log n)].
|
||||
*)
|
||||
|
||||
val take_exn : t -> t * elt
|
||||
(** Like {!take}, but can fail.
|
||||
(** [take_exn h] is like {!take}, but can fail.
|
||||
@raise Empty if the heap is empty. *)
|
||||
|
||||
val delete_one : (elt -> elt -> bool) -> elt -> t -> t
|
||||
(** Delete one occurrence of a value if it exist in the heap.
|
||||
[delete_one eq x h], use [eq] to find one [x] in [h] and delete it.
|
||||
If [h] do not contain [x] then it return [h].
|
||||
Complexity: [O(n)].
|
||||
@since 2.0 *)
|
||||
|
||||
val delete_all : (elt -> elt -> bool) -> elt -> t -> t
|
||||
|
|
@ -76,22 +86,27 @@ module type S = sig
|
|||
If [h] do not contain [x] then it return [h].
|
||||
The difference with {!filter} is that [delete_all] stops as soon as
|
||||
it enters a subtree whose root is bigger than the element.
|
||||
Complexity: [O(n log n)].
|
||||
@since 2.0 *)
|
||||
|
||||
val iter : (elt -> unit) -> t -> unit
|
||||
(** Iterate on elements. *)
|
||||
(** [iter f h] iterates over the heap [h] invoking [f] with the current element. *)
|
||||
|
||||
val fold : ('a -> elt -> 'a) -> 'a -> t -> 'a
|
||||
(** Fold on all values. *)
|
||||
(** [fold f acc h] folds on all values of [h]. *)
|
||||
|
||||
val size : t -> int
|
||||
(** Number of elements (linear complexity). *)
|
||||
(** [size h] is the number of elements in the heap [h].
|
||||
Complexity: [O(n)].
|
||||
*)
|
||||
|
||||
(** {2 Adding many elements at once} *)
|
||||
|
||||
val add_list : t -> elt list -> t
|
||||
(** [add_list h l] adds the elements of the list [l] into the heap [h].
|
||||
An element occurring several times will be added that many times to the heap.
|
||||
Complexity: [O(n log (m+n))]
|
||||
where [m] and [n] are the number of elements in [h] and [l], respectively.
|
||||
@since 0.16 *)
|
||||
|
||||
val add_iter : t -> elt iter -> t
|
||||
|
|
@ -136,6 +151,7 @@ module type S = sig
|
|||
val to_list : t -> elt list
|
||||
(** [to_list h] returns a list of the elements of the heap [h],
|
||||
in no particular order.
|
||||
Complexity: [O(n)].
|
||||
*)
|
||||
|
||||
val to_iter : t -> elt iter
|
||||
|
|
@ -153,6 +169,7 @@ module type S = sig
|
|||
val to_list_sorted : t -> elt list
|
||||
(** [to_list_sorted h] returns the list of elements of the heap [h]
|
||||
in increasing order.
|
||||
Complexity: [O(n log n)].
|
||||
@since 1.1 *)
|
||||
|
||||
val to_iter_sorted : t -> elt iter
|
||||
|
|
@ -168,7 +185,9 @@ module type S = sig
|
|||
|
||||
val to_tree : t -> elt ktree
|
||||
(** [to_tree h] returns a [ktree] of the elements of the heap [h].
|
||||
The layout is not specified. *)
|
||||
The layout is not specified.
|
||||
Complexity: [O(n)].
|
||||
*)
|
||||
|
||||
(** {2 Pretty-printing} *)
|
||||
|
||||
|
|
|
|||
|
|
@ -42,20 +42,27 @@ module type S = sig
|
|||
exception Empty
|
||||
|
||||
val merge : t -> t -> t
|
||||
(** [merge h1 h2] merges the two heaps [h1] and [h2]. *)
|
||||
(** [merge h1 h2] merges the two heaps [h1] and [h2].
|
||||
Complexity: [O(log (m+n))] where [m] and [n] are the number of elements in each heap.
|
||||
*)
|
||||
|
||||
val insert : elt -> t -> t
|
||||
(** [insert x h] inserts an element [x] into the heap [h]. *)
|
||||
(** [insert x h] inserts an element [x] into the heap [h].
|
||||
Complexity: [O(log n)] where [n] is the number of elements in [h].
|
||||
*)
|
||||
|
||||
val add : t -> elt -> t
|
||||
(** [add h x] inserts an element [x] into the heap [h]. *)
|
||||
(** [add h x] is [insert x h]. *)
|
||||
|
||||
val filter : (elt -> bool) -> t -> t
|
||||
(** [filter p h] filters values, only retaining the ones that satisfy the predicate [p].
|
||||
Linear time at least. *)
|
||||
Complexity: [O(n log n)].
|
||||
*)
|
||||
|
||||
val find_min : t -> elt option
|
||||
(** [find_min h] find the minimal element of the heap [h]. *)
|
||||
(** [find_min h] find the minimal element of the heap [h].
|
||||
Complexity: [O(1)].
|
||||
*)
|
||||
|
||||
val find_min_exn : t -> elt
|
||||
(** [find_min_exn h] is like {!find_min} but can fail.
|
||||
|
|
@ -63,7 +70,9 @@ module type S = sig
|
|||
|
||||
val take : t -> (t * elt) option
|
||||
(** [take h] extracts and returns the minimum element, and the new heap (without
|
||||
this element), or [None] if the heap [h] is empty. *)
|
||||
this element), or [None] if the heap [h] is empty.
|
||||
Complexity: [O(log n)].
|
||||
*)
|
||||
|
||||
val take_exn : t -> t * elt
|
||||
(** [take_exn h] is like {!take}, but can fail.
|
||||
|
|
@ -73,6 +82,7 @@ module type S = sig
|
|||
(** [delete_one eq x h] uses [eq] to find one occurrence of a value [x]
|
||||
if it exist in the heap [h], and delete it.
|
||||
If [h] do not contain [x] then it return [h].
|
||||
Complexity: [O(n)].
|
||||
@since 2.0 *)
|
||||
|
||||
val delete_all : (elt -> elt -> bool) -> elt -> t -> t
|
||||
|
|
@ -80,6 +90,7 @@ module type S = sig
|
|||
If [h] do not contain [x] then it return [h].
|
||||
The difference with {!filter} is that [delete_all] stops as soon as
|
||||
it enters a subtree whose root is bigger than the element.
|
||||
Complexity: [O(n log n)].
|
||||
@since 2.0 *)
|
||||
|
||||
val iter : (elt -> unit) -> t -> unit
|
||||
|
|
@ -89,13 +100,17 @@ module type S = sig
|
|||
(** [fold f acc h] folds on all values of [h]. *)
|
||||
|
||||
val size : t -> int
|
||||
(** [size h] is the number of elements in the heap [h]. Linear complexity. *)
|
||||
(** [size h] is the number of elements in the heap [h].
|
||||
Complexity: [O(n)].
|
||||
*)
|
||||
|
||||
(** {2 Adding many elements at once} *)
|
||||
|
||||
val add_list : t -> elt list -> t
|
||||
(** [add_list h l] adds the elements of the list [l] into the heap [h].
|
||||
An element occurring several times will be added that many times to the heap.
|
||||
Complexity: [O(n log (m+n))]
|
||||
where [m] and [n] are the number of elements in [h] and [l], respectively.
|
||||
@since 0.16 *)
|
||||
|
||||
val add_iter : t -> elt iter -> t
|
||||
|
|
@ -140,6 +155,7 @@ module type S = sig
|
|||
val to_list : t -> elt list
|
||||
(** [to_list h] returns a list of the elements of the heap [h],
|
||||
in no particular order.
|
||||
Complexity: [O(n)].
|
||||
*)
|
||||
|
||||
val to_iter : t -> elt iter
|
||||
|
|
@ -157,6 +173,7 @@ module type S = sig
|
|||
val to_list_sorted : t -> elt list
|
||||
(** [to_list_sorted h] returns the list of elements of the heap [h]
|
||||
in increasing order.
|
||||
Complexity: [O(n log n)].
|
||||
@since 1.1 *)
|
||||
|
||||
val to_iter_sorted : t -> elt iter
|
||||
|
|
@ -172,7 +189,9 @@ module type S = sig
|
|||
|
||||
val to_tree : t -> elt ktree
|
||||
(** [to_tree h] returns a [ktree] of the elements of the heap [h].
|
||||
The layout is not specified. *)
|
||||
The layout is not specified.
|
||||
Complexity: [O(n)].
|
||||
*)
|
||||
|
||||
(** {2 Pretty-printing} *)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue