Red-black trees #
This module implements a type RBMap α β cmp
which is a functional data structure for
storing a key-value store in a binary search tree.
It is built on the simpler RBSet α cmp
type, which stores a set of values of type α
using the function cmp : α → α → Ordering
for determining the ordering relation.
The tree will never store two elements that compare .eq
under the cmp
function,
but the function does not have to satisfy cmp x y = .eq → x = y
, and in the map case
α
is a key-value pair and the cmp
function only compares the keys.
In a red-black tree, every node has a color which is either "red" or "black" (this particular choice of colors is conventional). A nil node is considered black.
- red: Std.RBColor
A red node is required to have black children.
- black: Std.RBColor
Every path from the root to a leaf must pass through the same number of black nodes.
Instances For
Equations
- Std.instReprRBColor = { reprPrec := Std.reprRBColor✝ }
A red-black tree. (This is an internal implementation detail of the RBSet
type,
which includes the invariants of the tree.) This is a binary search tree augmented with
a "color" field which is either red or black for each node and used to implement
the re-balancing operations.
See: Red–black tree
- nil: {α : Type u} → Std.RBNode α
An empty tree.
- node: {α : Type u} → Std.RBColor → Std.RBNode α → α → Std.RBNode α → Std.RBNode α
Instances For
Equations
- Std.instReprRBNode = { reprPrec := Std.reprRBNode✝ }
Equations
- Std.RBNode.instEmptyCollectionRBNode = { emptyCollection := Std.RBNode.nil }
The minimum element of a tree is the left-most value.
Equations
- Std.RBNode.min Std.RBNode.nil = none
- Std.RBNode.min (Std.RBNode.node c Std.RBNode.nil v r) = some v
- Std.RBNode.min (Std.RBNode.node c l v r) = Std.RBNode.min l
Instances For
The maximum element of a tree is the right-most value.
Equations
- Std.RBNode.max Std.RBNode.nil = none
- Std.RBNode.max (Std.RBNode.node c l v Std.RBNode.nil) = some v
- Std.RBNode.max (Std.RBNode.node c l v r) = Std.RBNode.max r
Instances For
Fold a function in tree order along the nodes. v₀
is used at nil
nodes and
f
is used to combine results at branching nodes.
Equations
- Std.RBNode.fold v₀ f Std.RBNode.nil = v₀
- Std.RBNode.fold v₀ f (Std.RBNode.node a a_1 a_2 a_3) = f (Std.RBNode.fold v₀ f a_1) a_2 (Std.RBNode.fold v₀ f a_3)
Instances For
Fold a function on the values from left to right (in increasing order).
Equations
- Std.RBNode.foldl f x Std.RBNode.nil = x
- Std.RBNode.foldl f x (Std.RBNode.node c l v r) = Std.RBNode.foldl f (f (Std.RBNode.foldl f x l) v) r
Instances For
Fold a function on the values from right to left (in decreasing order).
Equations
- Std.RBNode.foldr f Std.RBNode.nil x = x
- Std.RBNode.foldr f (Std.RBNode.node c l v r) x = Std.RBNode.foldr f l (f v (Std.RBNode.foldr f r x))
Instances For
O(n)
. Convert the tree to a list in ascending order.
Equations
- Std.RBNode.toList t = Std.RBNode.foldr (fun (x : α) (x_1 : List α) => x :: x_1) t []
Instances For
Run monadic function f
on each element of the tree (in increasing order).
Equations
- Std.RBNode.forM f Std.RBNode.nil = pure PUnit.unit
- Std.RBNode.forM f (Std.RBNode.node a a_1 a_2 a_3) = do Std.RBNode.forM f a_1 f a_2 Std.RBNode.forM f a_3
Instances For
Fold a monadic function on the values from left to right (in increasing order).
Equations
- Std.RBNode.foldlM f x Std.RBNode.nil = pure x
- Std.RBNode.foldlM f x (Std.RBNode.node c l v r) = do let __do_lift ← Std.RBNode.foldlM f x l let __do_lift ← f __do_lift v Std.RBNode.foldlM f __do_lift r
Instances For
Implementation of for x in t
loops over a RBNode
(in increasing order).
Equations
- Std.RBNode.forIn as init f = ForInStep.run <$> Std.RBNode.forIn.visit f as init
Instances For
Inner loop of forIn
.
Equations
- Std.RBNode.forIn.visit f Std.RBNode.nil x = pure (ForInStep.yield x)
- Std.RBNode.forIn.visit f (Std.RBNode.node c l v r) x = ForInStep.bindM (Std.RBNode.forIn.visit f l x) fun (b : σ) => ForInStep.bindM (f v b) fun (x : σ) => Std.RBNode.forIn.visit f r x
Instances For
An auxiliary data structure (an iterator) over an RBNode
which lazily
pulls elements from the left.
- nil: {α : Type u_1} → Std.RBNode.Stream α
The stream is empty.
- cons: {α : Type u_1} → α → Std.RBNode α → Std.RBNode.Stream α → Std.RBNode.Stream α
We are ready to deliver element
v
with right childr
, and wheretail
represents all the subtrees we have yet to destructure.
Instances For
O(log n)
. Turn a node into a stream, by descending along the left spine.
Equations
- Std.RBNode.toStream Std.RBNode.nil x = x
- Std.RBNode.toStream (Std.RBNode.node c l v r) x = Std.RBNode.toStream l (Std.RBNode.Stream.cons v r x)
Instances For
O(1)
amortized, O(log n)
worst case: Get the next element from the stream.
Equations
- Std.RBNode.Stream.next? x = match x with | Std.RBNode.Stream.nil => none | Std.RBNode.Stream.cons v r tail => some (v, Std.RBNode.toStream r tail)
Instances For
Fold a function on the values from left to right (in increasing order).
Equations
- Std.RBNode.Stream.foldl f x Std.RBNode.Stream.nil = x
- Std.RBNode.Stream.foldl f x (Std.RBNode.Stream.cons v r tail) = Std.RBNode.Stream.foldl f (Std.RBNode.foldl f (f x v) r) tail
Instances For
Fold a function on the values from right to left (in decreasing order).
Equations
- Std.RBNode.Stream.foldr f Std.RBNode.Stream.nil x = x
- Std.RBNode.Stream.foldr f (Std.RBNode.Stream.cons v r tail) x = f v (Std.RBNode.foldr f r (Std.RBNode.Stream.foldr f tail x))
Instances For
O(n)
. Convert the stream to a list in ascending order.
Equations
- Std.RBNode.Stream.toList t = Std.RBNode.Stream.foldr (fun (x : α) (x_1 : List α) => x :: x_1) t []
Instances For
Equations
- Std.RBNode.instToStreamRBNodeStream = { toStream := fun (x : Std.RBNode α) => Std.RBNode.toStream x }
Equations
- Std.RBNode.instStreamStream = { next? := Std.RBNode.Stream.next? }
Returns true
iff every element of the tree satisfies p
.
Equations
- Std.RBNode.all p Std.RBNode.nil = true
- Std.RBNode.all p (Std.RBNode.node a a_1 a_2 a_3) = (p a_2 && Std.RBNode.all p a_1 && Std.RBNode.all p a_3)
Instances For
Returns true
iff any element of the tree satisfies p
.
Equations
- Std.RBNode.any p Std.RBNode.nil = false
- Std.RBNode.any p (Std.RBNode.node a a_1 a_2 a_3) = (p a_2 || Std.RBNode.any p a_1 || Std.RBNode.any p a_3)
Instances For
Asserts that p
holds on every element of the tree.
Equations
- Std.RBNode.All p Std.RBNode.nil = True
- Std.RBNode.All p (Std.RBNode.node a a_1 a_2 a_3) = (p a_2 ∧ Std.RBNode.All p a_1 ∧ Std.RBNode.All p a_3)
Instances For
Equations
- Std.RBNode.instDecidableAll = decidable_of_iff (Std.RBNode.all (fun (b : α) => decide (p b)) t = true) (_ : Std.RBNode.all (fun (b : α) => decide (p b)) t = true ↔ Std.RBNode.All p t)
Asserts that p
holds on some element of the tree.
Equations
- Std.RBNode.Any p Std.RBNode.nil = False
- Std.RBNode.Any p (Std.RBNode.node a a_1 a_2 a_3) = (p a_2 ∨ Std.RBNode.Any p a_1 ∨ Std.RBNode.Any p a_3)
Instances For
Equations
- Std.RBNode.instDecidableAny = decidable_of_iff (Std.RBNode.any (fun (b : α) => decide (p b)) t = true) (_ : Std.RBNode.any (fun (b : α) => decide (p b)) t = true ↔ Std.RBNode.Any p t)
True if x
is an element of t
"exactly", i.e. up to equality, not the cmp
relation.
Equations
- Std.RBNode.EMem x t = Std.RBNode.Any (fun (x_1 : α) => x = x_1) t
Instances For
Equations
- Std.RBNode.instMembershipRBNode = { mem := Std.RBNode.EMem }
True if the specified cut
matches at least one element of of t
.
Equations
- Std.RBNode.MemP cut t = Std.RBNode.Any (fun (x : α) => cut x = Ordering.eq) t
Instances For
True if x
is equivalent to an element of t
.
Equations
- Std.RBNode.Mem cmp x t = Std.RBNode.MemP (cmp x) t
Instances For
Equations
- Std.RBNode.Slow.instDecidableEMem = inferInstanceAs (Decidable (Std.RBNode.Any (fun (x_1 : α) => x = x_1) t))
Instances For
Equations
- Std.RBNode.Slow.instDecidableMemP = inferInstanceAs (Decidable (Std.RBNode.Any (fun (x : α) => cut x = Ordering.eq) t))
Instances For
Equations
- Std.RBNode.Slow.instDecidableMem = inferInstanceAs (Decidable (Std.RBNode.Any (fun (x_1 : α) => cmp x x_1 = Ordering.eq) t))
Instances For
Asserts that t₁
and t₂
have the same number of elements in the same order,
and R
holds pairwise between them. The tree structure is ignored.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Equations
- Std.RBNode.instBEqRBNode = { beq := fun (a b : Std.RBNode α) => Std.RBNode.all₂ (fun (x x_1 : α) => x == x_1) a b }
We say that x < y
under the comparator cmp
if cmp x y = .lt
.
- In order to avoid assuming the comparator is always lawful, we use a
local
∀ [TransCmp cmp]
binder in the relation so that the ordering properties of the tree only need to hold if the comparator is lawful. - The
Nonempty
wrapper is a no-op because this is already a proposition, but it prevents the[TransCmp cmp]
binder from being introduced when we don't want it.
Equations
- Std.RBNode.cmpLT cmp x y = Nonempty (∀ [inst : Std.TransCmp cmp], cmp x y = Ordering.lt)
Instances For
Equations
- Std.RBNode.instDecidableCmpLT cmp = decidable_of_iff' (cmp x y = Ordering.lt) (_ : Std.RBNode.cmpLT cmp x y ↔ cmp x y = Ordering.lt)
We say that x ≈ y
under the comparator cmp
if cmp x y = .eq
. See also cmpLT
.
Equations
- Std.RBNode.cmpEq cmp x y = Nonempty (∀ [inst : Std.TransCmp cmp], cmp x y = Ordering.eq)
Instances For
Equations
- Std.RBNode.instDecidableCmpEq cmp = decidable_of_iff' (cmp x y = Ordering.eq) (_ : Std.RBNode.cmpEq cmp x y ↔ cmp x y = Ordering.eq)
O(n)
. Verifies an ordering relation on the nodes of the tree.
Equations
- Std.RBNode.isOrdered cmp Std.RBNode.nil l r = match l, r with | some l, some r => decide (cmp l r = Ordering.lt) | x, x_1 => true
- Std.RBNode.isOrdered cmp (Std.RBNode.node a a_1 a_2 a_3) l r = (Std.RBNode.isOrdered cmp a_1 l (some a_2) && Std.RBNode.isOrdered cmp a_3 (some a_2) r)
Instances For
The first half of Okasaki's balance
, concerning red-red sequences in the left child.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The second half of Okasaki's balance
, concerning red-red sequences in the right child.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Returns red
if the node is red, otherwise black
. (Nil nodes are treated as black
.)
Equations
- Std.RBNode.isRed x = match x with | Std.RBNode.node c l v r => c | x => Std.RBColor.black
Instances For
Returns black
if the node is black, otherwise red
.
(Nil nodes are treated as red
, which is not the usual convention but useful for deletion.)
Equations
- Std.RBNode.isBlack x = match x with | Std.RBNode.node c l v r => c | x => Std.RBColor.red
Instances For
Change the color of the root to black
.
Equations
- Std.RBNode.setBlack x = match x with | Std.RBNode.nil => Std.RBNode.nil | Std.RBNode.node c l v r => Std.RBNode.node Std.RBColor.black l v r
Instances For
The core of the insert
function. This adds an element x
to a balanced red-black tree.
Importantly, the result of calling ins
is not a proper red-black tree,
because it has a broken balance invariant.
(See Balanced.ins
for the balance invariant of ins
.)
The insert
function does the final fixup needed to restore the invariant.
Equations
- One or more equations did not get rendered due to their size.
- Std.RBNode.ins cmp x Std.RBNode.nil = Std.RBNode.node Std.RBColor.red Std.RBNode.nil x Std.RBNode.nil
Instances For
insert cmp t v
inserts element v
into the tree, using the provided comparator
cmp
to put it in the right place and automatically rebalancing the tree as necessary.
Equations
- Std.RBNode.insert cmp t v = match Std.RBNode.isRed t with | Std.RBColor.red => Std.RBNode.setBlack (Std.RBNode.ins cmp v t) | Std.RBColor.black => Std.RBNode.ins cmp v t
Instances For
Recolor the root of the tree to red
if possible.
Equations
- Std.RBNode.setRed x = match x with | Std.RBNode.node c a v b => Std.RBNode.node Std.RBColor.red a v b | Std.RBNode.nil => Std.RBNode.nil
Instances For
Rebalancing a tree which has shrunk on the left.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Rebalancing a tree which has shrunk on the right.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The number of nodes in the tree.
Equations
- Std.RBNode.size Std.RBNode.nil = 0
- Std.RBNode.size (Std.RBNode.node a a_1 a_2 a_3) = Std.RBNode.size a_1 + Std.RBNode.size a_3 + 1
Instances For
Concatenate two trees with the same black-height.
Equations
- One or more equations did not get rendered due to their size.
- Std.RBNode.append Std.RBNode.nil x = x
- Std.RBNode.append x Std.RBNode.nil = x
Instances For
erase #
The core of the erase
function. The tree returned from this function has a broken invariant,
which is restored in erase
.
Equations
- One or more equations did not get rendered due to their size.
- Std.RBNode.del cut Std.RBNode.nil = Std.RBNode.nil
Instances For
The erase cut t
function removes an element from the tree t
.
The cut
function is used to locate an element in the tree:
it returns .gt
if we go too high and .lt
if we go too low;
if it returns .eq
we will remove the element.
(The function cmp k
for some key k
is a valid cut function, but we can also use cuts that
are not of this form as long as they are suitably monotonic.)
Equations
- Std.RBNode.erase cut t = Std.RBNode.setBlack (Std.RBNode.del cut t)
Instances For
Finds an element in the tree satisfying the cut
function.
Equations
- One or more equations did not get rendered due to their size.
- Std.RBNode.find? cut Std.RBNode.nil = none
Instances For
lowerBound? cut
retrieves the largest entry smaller than or equal to cut
, if it exists.
Equations
- One or more equations did not get rendered due to their size.
- Std.RBNode.lowerBound? cut Std.RBNode.nil x = x
Instances For
Returns the root of the tree, if any.
Equations
- Std.RBNode.root? x = match x with | Std.RBNode.nil => none | Std.RBNode.node c l v r => some v
Instances For
O(n)
. Map a function on every value in the tree.
This requires IsMonotone
on the function in order to preserve the order invariant.
Equations
- Std.RBNode.map f Std.RBNode.nil = Std.RBNode.nil
- Std.RBNode.map f (Std.RBNode.node a a_1 a_2 a_3) = Std.RBNode.node a (Std.RBNode.map f a_1) (f a_2) (Std.RBNode.map f a_3)
Instances For
Converts the tree into an array in increasing sorted order.
Equations
- Std.RBNode.toArray n = Std.RBNode.foldl (fun (x : Array α) (x_1 : α) => Array.push x x_1) #[] n
Instances For
A RBNode.Path α
is a "cursor" into an RBNode
which represents the path
from the root to a subtree. Note that the path goes from the target subtree
up to the root, which is reversed from the normal way data is stored in the tree.
See Zipper for more information.
- root: {α : Type u} → Std.RBNode.Path α
The root of the tree, which is the end of the path of parents.
- left: {α : Type u} → Std.RBColor → Std.RBNode.Path α → α → Std.RBNode α → Std.RBNode.Path α
A path that goes down the left subtree.
- right: {α : Type u} → Std.RBColor → Std.RBNode α → α → Std.RBNode.Path α → Std.RBNode.Path α
A path that goes down the right subtree.
Instances For
Fills the Path
with a subtree.
Equations
- Std.RBNode.Path.fill Std.RBNode.Path.root x = x
- Std.RBNode.Path.fill (Std.RBNode.Path.left c parent y b) x = Std.RBNode.Path.fill parent (Std.RBNode.node c x y b)
- Std.RBNode.Path.fill (Std.RBNode.Path.right c a y parent) x = Std.RBNode.Path.fill parent (Std.RBNode.node c a y x)
Instances For
Like find?
, but instead of just returning the element, it returns the entire subtree
at the element and a path back to the root for reconstructing the tree.
Equations
- One or more equations did not get rendered due to their size.
- Std.RBNode.zoom cut Std.RBNode.nil x = (Std.RBNode.nil, x)
Instances For
This function does the second part of RBNode.ins
,
which unwinds the stack and rebuilds the tree.
Equations
- Std.RBNode.Path.ins Std.RBNode.Path.root x = Std.RBNode.setBlack x
- Std.RBNode.Path.ins (Std.RBNode.Path.left Std.RBColor.red parent y b) x = Std.RBNode.Path.ins parent (Std.RBNode.node Std.RBColor.red x y b)
- Std.RBNode.Path.ins (Std.RBNode.Path.right Std.RBColor.red a y parent) x = Std.RBNode.Path.ins parent (Std.RBNode.node Std.RBColor.red a y x)
- Std.RBNode.Path.ins (Std.RBNode.Path.left Std.RBColor.black parent y b) x = Std.RBNode.Path.ins parent (Std.RBNode.balance1 x y b)
- Std.RBNode.Path.ins (Std.RBNode.Path.right Std.RBColor.black a y parent) x = Std.RBNode.Path.ins parent (Std.RBNode.balance2 a y x)
Instances For
path.insertNew v
inserts element v
into the tree, assuming that path
is zoomed in
on a nil
node such that inserting a new element at this position is valid.
Equations
- Std.RBNode.Path.insertNew path v = Std.RBNode.Path.ins path (Std.RBNode.node Std.RBColor.red Std.RBNode.nil v Std.RBNode.nil)
Instances For
path.insert t v
inserts element v
into the tree, assuming that (t, path)
was the result of a
previous zoom
operation (so either the root of t
is equivalent to v
or it is empty).
Equations
- Std.RBNode.Path.insert path t v = match t with | Std.RBNode.nil => Std.RBNode.Path.insertNew path v | Std.RBNode.node c a v_1 b => Std.RBNode.Path.fill path (Std.RBNode.node c a v b)
Instances For
path.del t c
does the second part of RBNode.del
, which unwinds the stack
and rebuilds the tree. The c
argument is the color of the node before the deletion
(we used t₀.isBlack
for this in RBNode.del
but the original tree is no longer
available in this formulation).
Equations
- Std.RBNode.Path.del Std.RBNode.Path.root x✝ x = Std.RBNode.setBlack x✝
- Std.RBNode.Path.del (Std.RBNode.Path.left c parent y b) x Std.RBColor.red = Std.RBNode.Path.del parent (Std.RBNode.node Std.RBColor.red x y b) c
- Std.RBNode.Path.del (Std.RBNode.Path.right c a y parent) x Std.RBColor.red = Std.RBNode.Path.del parent (Std.RBNode.node Std.RBColor.red a y x) c
- Std.RBNode.Path.del (Std.RBNode.Path.left c parent y b) x Std.RBColor.black = Std.RBNode.Path.del parent (Std.RBNode.balLeft x y b) c
- Std.RBNode.Path.del (Std.RBNode.Path.right c a y parent) x Std.RBColor.black = Std.RBNode.Path.del parent (Std.RBNode.balRight a y x) c
Instances For
path.erase t v
removes the root element of t
from the tree, assuming that (t, path)
was
the result of a previous zoom
operation.
Equations
- Std.RBNode.Path.erase path t = match t with | Std.RBNode.nil => Std.RBNode.Path.fill path Std.RBNode.nil | Std.RBNode.node c a v b => Std.RBNode.Path.del path (Std.RBNode.append a b) c
Instances For
modify cut f t
uses cut
to find an element,
then modifies the element using f
and reinserts it into the tree.
Because the tree structure is not modified,
f
must not modify the ordering properties of the element.
The element in t
is used linearly if t
is unshared.
Equations
- Std.RBNode.modify cut f t = match Std.RBNode.zoom cut t with | (Std.RBNode.nil, snd) => t | (Std.RBNode.node c a x b, path) => Std.RBNode.Path.fill path (Std.RBNode.node c a (f x) b)
Instances For
alter cut f t
simultaneously handles inserting, erasing and replacing an element
using a function f : Option α → Option α
. It is passed the result of t.find? cut
and can either return none
to remove the element or some a
to replace/insert
the element with a
(which must have the same ordering properties as the original element).
The element is used linearly if t
is unshared.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The ordering invariant of a red-black tree, which is a binary search tree.
This says that every element of a left subtree is less than the root, and
every element in the right subtree is greater than the root, where the
less than relation x < y
is understood to mean cmp x y = .lt
.
Because we do not assume that cmp
is lawful when stating this property,
we write it in such a way that if cmp
is not lawful then the condition holds trivially.
That way we can prove the ordering invariants without assuming cmp
is lawful.
Equations
- One or more equations did not get rendered due to their size.
- Std.RBNode.Ordered cmp Std.RBNode.nil = True
Instances For
Equations
- One or more equations did not get rendered due to their size.
- Std.RBNode.Slow.instDecidableOrdered cmp Std.RBNode.nil = inferInstanceAs (Decidable True)
Instances For
The red-black balance invariant. Balanced t c n
says that the color of the root node is c
,
and the black-height (the number of black nodes on any path from the root) of the tree is n
.
Additionally, every red node must have black children.
- nil: ∀ {α : Type u_1}, Std.RBNode.Balanced Std.RBNode.nil Std.RBColor.black 0
A nil node is balanced with black-height 0, and it is considered black.
- red: ∀ {α : Type u_1} {x : Std.RBNode α} {n : Nat} {y : Std.RBNode α} {v : α},
Std.RBNode.Balanced x Std.RBColor.black n →
Std.RBNode.Balanced y Std.RBColor.black n →
Std.RBNode.Balanced (Std.RBNode.node Std.RBColor.red x v y) Std.RBColor.red n
A red node is balanced with black-height
n
if its children are both black with with black-heightn
. - black: ∀ {α : Type u_1} {x : Std.RBNode α} {c₁ : Std.RBColor} {n : Nat} {y : Std.RBNode α} {c₂ : Std.RBColor} {v : α},
Std.RBNode.Balanced x c₁ n →
Std.RBNode.Balanced y c₂ n → Std.RBNode.Balanced (Std.RBNode.node Std.RBColor.black x v y) Std.RBColor.black (n + 1)
A black node is balanced with black-height
n + 1
if its children both have black-heightn
.
Instances For
The well-formedness invariant for a red-black tree. The first constructor is the real invariant,
and the others allow us to "cheat" in this file and define insert
and erase
,
which have more complex proofs that are delayed to Std.Data.RBMap.Lemmas
.
- mk: ∀ {α : Type u_1} {cmp : α → α → Ordering} {t : Std.RBNode α} {c : Std.RBColor} {n : Nat},
Std.RBNode.Ordered cmp t → Std.RBNode.Balanced t c n → Std.RBNode.WF cmp t
The actual well-formedness invariant: a red-black tree has the ordering and balance invariants.
- insert: ∀ {α : Type u_1} {cmp : α → α → Ordering} {t : Std.RBNode α} {a : α}, Std.RBNode.WF cmp t → Std.RBNode.WF cmp (Std.RBNode.insert cmp t a)
- erase: ∀ {α : Type u_1} {cmp : α → α → Ordering} {t : Std.RBNode α} {cut : α → Ordering}, Std.RBNode.WF cmp t → Std.RBNode.WF cmp (Std.RBNode.erase cut t)
Instances For
An RBSet
is a self-balancing binary search tree.
The cmp
function is the comparator that will be used for performing searches;
it should satisfy the requirements of TransCmp
for it to have sensible behavior.
Equations
- Std.RBSet α cmp = { t : Std.RBNode α // Std.RBNode.WF cmp t }
Instances For
O(1)
. Construct a new empty tree.
Equations
- Std.mkRBSet α cmp = { val := Std.RBNode.nil, property := (_ : Std.RBNode.WF cmp Std.RBNode.nil) }
Instances For
O(1)
. Construct a new empty tree.
Equations
- Std.RBSet.empty = Std.mkRBSet α cmp
Instances For
Equations
- Std.RBSet.instEmptyCollectionRBSet α cmp = { emptyCollection := Std.RBSet.empty }
Equations
- Std.RBSet.instInhabitedRBSet α cmp = { default := ∅ }
O(1)
. Construct a new tree with one element v
.
Equations
- One or more equations did not get rendered due to their size.
Instances For
O(n)
. Fold a function on the values from left to right (in increasing order).
Equations
- Std.RBSet.foldl f init t = Std.RBNode.foldl f init t.val
Instances For
O(n)
. Fold a function on the values from right to left (in decreasing order).
Equations
- Std.RBSet.foldr f init t = Std.RBNode.foldr f t.val init
Instances For
O(n)
. Fold a monadic function on the values from left to right (in increasing order).
Equations
- Std.RBSet.foldlM f init t = Std.RBNode.foldlM f init t.val
Instances For
O(n)
. Run monadic function f
on each element of the tree (in increasing order).
Equations
- Std.RBSet.forM f t = Std.RBNode.forM f t.val
Instances For
Equations
- Std.RBSet.instToStreamRBSetStream = { toStream := fun (x : Std.RBSet α cmp) => Std.RBNode.toStream x.val }
O(1)
. Is the tree empty?
Equations
- Std.RBSet.isEmpty x = match x with | { val := Std.RBNode.nil, property := property } => true | x => false
Instances For
O(n)
. Convert the tree to a list in ascending order.
Equations
- Std.RBSet.toList t = Std.RBNode.toList t.val
Instances For
O(log n)
. Returns the entry a
such that a ≤ k
for all keys in the RBSet.
Equations
- Std.RBSet.min t = Std.RBNode.min t.val
Instances For
O(log n)
. Returns the entry a
such that a ≥ k
for all keys in the RBSet.
Equations
- Std.RBSet.max t = Std.RBNode.max t.val
Instances For
Equations
- Std.RBSet.instReprRBSet = { reprPrec := fun (m : Std.RBSet α cmp) (prec : Nat) => Repr.addAppParen (Std.Format.text "RBSet.ofList " ++ repr (Std.RBSet.toList m)) prec }
O(log n)
. Insert element v
into the tree.
Equations
- Std.RBSet.insert t v = { val := Std.RBNode.insert cmp t.val v, property := (_ : Std.RBNode.WF cmp (Std.RBNode.insert cmp t.val v)) }
Instances For
O(log n)
. Remove an element from the tree using a cut function.
The cut
function is used to locate an element in the tree:
it returns .gt
if we go too high and .lt
if we go too low;
if it returns .eq
we will remove the element.
(The function cmp k
for some key k
is a valid cut function, but we can also use cuts that
are not of this form as long as they are suitably monotonic.)
Equations
- Std.RBSet.erase t cut = { val := Std.RBNode.erase cut t.val, property := (_ : Std.RBNode.WF cmp (Std.RBNode.erase cut t.val)) }
Instances For
O(log n)
. Find an element in the tree using a cut function.
Equations
- Std.RBSet.findP? t cut = Std.RBNode.find? cut t.val
Instances For
O(log n)
. Returns an element in the tree equivalent to x
if one exists.
Equations
- Std.RBSet.find? t x = Std.RBNode.find? (cmp x) t.val
Instances For
O(log n)
. Find an element in the tree, or return a default value v₀
.
Equations
- Std.RBSet.findPD t cut v₀ = Option.getD (Std.RBSet.findP? t cut) v₀
Instances For
O(log n)
. lowerBoundP cut
retrieves the largest entry comparing lt
or eq
under cut
,
if it exists.
Equations
- Std.RBSet.lowerBoundP? t cut = Std.RBNode.lowerBound? cut t.val none
Instances For
O(log n)
. lowerBound? k
retrieves the largest entry smaller than or equal to k
,
if it exists.
Equations
- Std.RBSet.lowerBound? t k = Std.RBNode.lowerBound? (cmp k) t.val none
Instances For
O(log n)
. Returns true if the given cut returns eq
for something in the RBSet.
Equations
- Std.RBSet.containsP t cut = Option.isSome (Std.RBSet.findP? t cut)
Instances For
O(log n)
. Returns true if the given key a
is in the RBSet.
Equations
- Std.RBSet.contains t a = Option.isSome (Std.RBSet.find? t a)
Instances For
O(n log n)
. Build a tree from an unsorted list by inserting them one at a time.
Equations
- Std.RBSet.ofList l cmp = List.foldl (fun (r : Std.RBSet α cmp) (p : α) => Std.RBSet.insert r p) (Std.mkRBSet α cmp) l
Instances For
O(n log n)
. Build a tree from an unsorted array by inserting them one at a time.
Equations
- Std.RBSet.ofArray l cmp = Array.foldl (fun (r : Std.RBSet α cmp) (p : α) => Std.RBSet.insert r p) (Std.mkRBSet α cmp) l 0
Instances For
O(n)
. Returns true if the given predicate is true for all items in the RBSet.
Equations
- Std.RBSet.all t p = Std.RBNode.all p t.val
Instances For
O(n)
. Returns true if the given predicate is true for any item in the RBSet.
Equations
- Std.RBSet.any t p = Std.RBNode.any p t.val
Instances For
Asserts that t₁
and t₂
have the same number of elements in the same order,
and R
holds pairwise between them. The tree structure is ignored.
Equations
- Std.RBSet.all₂ R t₁ t₂ = Std.RBNode.all₂ R t₁.val t₂.val
Instances For
True if x
is an element of t
"exactly", i.e. up to equality, not the cmp
relation.
Equations
- Std.RBSet.EMem x t = Std.RBNode.EMem x t.val
Instances For
True if the specified cut
matches at least one element of of t
.
Equations
- Std.RBSet.MemP cut t = Std.RBNode.MemP cut t.val
Instances For
True if x
is equivalent to an element of t
.
Equations
- Std.RBSet.Mem x t = Std.RBSet.MemP (cmp x) t
Instances For
Equations
- Std.RBSet.instMembershipRBSet = { mem := Std.RBSet.Mem }
Equations
- Std.RBSet.Slow.instDecidableEMem = inferInstanceAs (Decidable (Std.RBNode.Any (fun (x_1 : α) => x = x_1) t.val))
Instances For
Equations
- Std.RBSet.Slow.instDecidableMemP = inferInstanceAs (Decidable (Std.RBNode.Any (fun (x : α) => cut x = Ordering.eq) t.val))
Instances For
Equations
- Std.RBSet.Slow.instDecidableMem = inferInstanceAs (Decidable (Std.RBNode.Any (fun (x_1 : α) => cmp x x_1 = Ordering.eq) t.val))
Instances For
Returns true if t₁
and t₂
are equal as sets (assuming cmp
and ==
are compatible),
ignoring the internal tree structure.
Equations
- Std.RBSet.instBEqRBSet = { beq := fun (a b : Std.RBSet α cmp) => Std.RBSet.all₂ (fun (x x_1 : α) => x == x_1) a b }
O(n)
. The number of items in the RBSet.
Equations
- Std.RBSet.size m = Std.RBNode.size m.val
Instances For
O(log n)
. Returns the minimum element of the tree, or panics if the tree is empty.
Equations
- Std.RBSet.min! t = Option.getD (Std.RBSet.min t) (panicWithPosWithDecl "Std.Data.RBMap.Basic" "Std.RBSet.min!" 755 70 "tree is empty")
Instances For
O(log n)
. Returns the maximum element of the tree, or panics if the tree is empty.
Equations
- Std.RBSet.max! t = Option.getD (Std.RBSet.max t) (panicWithPosWithDecl "Std.Data.RBMap.Basic" "Std.RBSet.max!" 758 70 "tree is empty")
Instances For
O(log n)
. Attempts to find the value with key k : α
in t
and panics if there is no such key.
Equations
- Std.RBSet.findP! t cut = Option.getD (Std.RBSet.findP? t cut) (panicWithPosWithDecl "Std.Data.RBMap.Basic" "Std.RBSet.findP!" 764 23 "key is not in the tree")
Instances For
O(log n)
. Attempts to find the value with key k : α
in t
and panics if there is no such key.
Equations
- Std.RBSet.find! t k = Option.getD (Std.RBSet.find? t k) (panicWithPosWithDecl "Std.Data.RBMap.Basic" "Std.RBSet.find!" 770 20 "key is not in the tree")
Instances For
The predicate asserting that the result of modifyP
is safe to construct.
- wf : Std.RBNode.WF cmp (Std.RBNode.modify cut f t.val)
The resulting tree is well formed.
Instances
O(log n)
. In-place replace an element found by cut
.
This takes the element out of the tree while f
runs,
so it uses the element linearly if t
is unshared.
The ModifyWF
assumption is required because f
may change
the ordering properties of the element, which would break the invariants.
Equations
- Std.RBSet.modifyP t cut f = { val := Std.RBNode.modify cut f t.val, property := (_ : Std.RBNode.WF cmp (Std.RBNode.modify cut f t.val)) }
Instances For
The predicate asserting that the result of alterP
is safe to construct.
- wf : Std.RBNode.WF cmp (Std.RBNode.alter cut f t.val)
The resulting tree is well formed.
Instances
O(log n)
. alterP cut f t
simultaneously handles inserting, erasing and replacing an element
using a function f : Option α → Option α
. It is passed the result of t.findP? cut
and can either return none
to remove the element or some a
to replace/insert
the element with a
(which must have the same ordering properties as the original element).
The element is used linearly if t
is unshared.
The AlterWF
assumption is required because f
may change
the ordering properties of the element, which would break the invariants.
Equations
- Std.RBSet.alterP t cut f = { val := Std.RBNode.alter cut f t.val, property := (_ : Std.RBNode.WF cmp (Std.RBNode.alter cut f t.val)) }
Instances For
O(n₂ * log (n₁ + n₂))
. Merges the maps t₁
and t₂
.
If equal keys exist in both, the key from t₂
is preferred.
Equations
- Std.RBSet.union t₁ t₂ = Std.RBSet.foldl Std.RBSet.insert t₁ t₂
Instances For
O(n₂ * log (n₁ + n₂))
. Merges the maps t₁
and t₂
. If equal keys exist in both,
then use mergeFn a₁ a₂
to produce the new merged value.
Equations
- One or more equations did not get rendered due to their size.
Instances For
O(n₁ * log (n₁ + n₂))
. Intersects the maps t₁
and t₂
using mergeFn a b
to produce the new value.
Equations
- One or more equations did not get rendered due to their size.
Instances For
O(n * log n)
. Constructs the set of all elements satisfying p
.
Equations
- Std.RBSet.filter t p = Std.RBSet.foldl (fun (acc : Std.RBSet α cmp) (a : α) => bif p a then Std.RBSet.insert acc a else acc) ∅ t
Instances For
O(n * log n)
. Map a function on every value in the set.
If the function is monotone, consider using the more efficient RBSet.mapMonotone
instead.
Equations
- Std.RBSet.map t f = Std.RBSet.foldl (fun (acc : Std.RBSet β cmpβ) (a : α) => Std.RBSet.insert acc (f a)) ∅ t
Instances For
O(n₁ * (log n₁ + log n₂))
. Constructs the set of all elements of t₁
that are not in t₂
.
Equations
- Std.RBSet.sdiff t₁ t₂ = Std.RBSet.filter t₁ fun (x : α) => !Std.RBSet.contains t₂ x
Instances For
An RBMap
is a self-balancing binary search tree, used to store a key-value map.
The cmp
function is the comparator that will be used for performing searches;
it should satisfy the requirements of TransCmp
for it to have sensible behavior.
Equations
- Std.RBMap α β cmp = Std.RBSet (α × β) (Ordering.byKey Prod.fst cmp)
Instances For
O(1)
. Construct a new empty map.
Equations
- Std.mkRBMap α β cmp = Std.mkRBSet (α × β) (Ordering.byKey Prod.fst cmp)
Instances For
O(1)
. Construct a new empty map.
Equations
- Std.RBMap.empty = Std.mkRBMap α β cmp
Instances For
Equations
- Std.instEmptyCollectionRBMap α β cmp = { emptyCollection := Std.RBMap.empty }
Equations
- Std.instInhabitedRBMap α β cmp = { default := ∅ }
O(1)
. Construct a new tree with one key-value pair k, v
.
Equations
- Std.RBMap.single k v = Std.RBSet.single (k, v)
Instances For
O(n)
. Fold a function on the values from left to right (in increasing order).
Equations
- One or more equations did not get rendered due to their size.
Instances For
O(n)
. Fold a function on the values from right to left (in decreasing order).
Equations
- One or more equations did not get rendered due to their size.
Instances For
O(n)
. Fold a monadic function on the values from left to right (in increasing order).
Equations
- One or more equations did not get rendered due to their size.
Instances For
O(n)
. Run monadic function f
on each element of the tree (in increasing order).
Equations
- Std.RBMap.forM f t = Std.RBMap.foldlM (fun (x : PUnit) (k : α) (v : β) => f k v) PUnit.unit t
Instances For
Equations
- Std.RBMap.instToStreamRBMapStreamProd = inferInstanceAs (ToStream (Std.RBSet (α × β) (Ordering.byKey Prod.fst cmp)) (Std.RBNode.Stream (α × β)))
O(n)
. Constructs the array of keys of the map.
Equations
- Std.RBMap.keysArray t = Std.RBNode.foldl (fun (x : Array α) (x_1 : α × β) => Array.push x x_1.fst) #[] t.val
Instances For
O(n)
. Constructs the list of keys of the map.
Equations
- Std.RBMap.keysList t = Std.RBNode.foldr (fun (x : α × β) (x_1 : List α) => x.fst :: x_1) t.val []
Instances For
An "iterator" over the keys of the map. This is a trivial wrapper over the underlying map,
but it comes with a small API to use it in a for
loop or convert it to an array or list.
Equations
- Std.RBMap.Keys α β cmp = Std.RBMap α β cmp
Instances For
The keys of the map. This is an O(1)
wrapper operation, which
can be used in for
loops or converted to an array or list.
Equations
- Std.RBMap.keys t = t
Instances For
Equations
- Std.RBMap.instCoeHeadKeysArray = { coe := Std.RBMap.keysArray }
Equations
- Std.RBMap.instCoeHeadKeysList = { coe := Std.RBMap.keysList }
Equations
- One or more equations did not get rendered due to their size.
Equations
- Std.RBMap.instForMKeys = { forM := fun [Monad m] (t : Std.RBMap.Keys α β cmp) (f : α → m PUnit) => Std.RBNode.forM (fun (x : α × β) => f x.fst) t.val }
The result of toStream
on a Keys
.
Equations
- Std.RBMap.Keys.Stream α β = Std.RBNode.Stream (α × β)
Instances For
A stream over the iterator.
Equations
Instances For
O(1)
amortized, O(log n)
worst case: Get the next element from the stream.
Equations
- Std.RBMap.Keys.Stream.next? t = match inline (Std.RBNode.Stream.next? t) with | none => none | some ((a, snd), t) => some (a, t)
Instances For
Equations
- Std.RBMap.instToStreamKeysStream = { toStream := Std.RBMap.Keys.toStream }
Equations
- Std.RBMap.instStreamStream = { next? := Std.RBMap.Keys.Stream.next? }
O(n)
. Constructs the array of values of the map.
Equations
- Std.RBMap.valuesArray t = Std.RBNode.foldl (fun (x : Array β) (x_1 : α × β) => Array.push x x_1.snd) #[] t.val
Instances For
O(n)
. Constructs the list of values of the map.
Equations
- Std.RBMap.valuesList t = Std.RBNode.foldr (fun (x : α × β) (x_1 : List β) => x.snd :: x_1) t.val []
Instances For
An "iterator" over the values of the map. This is a trivial wrapper over the underlying map,
but it comes with a small API to use it in a for
loop or convert it to an array or list.
Equations
- Std.RBMap.Values α β cmp = Std.RBMap α β cmp
Instances For
The "keys" of the map. This is an O(1)
wrapper operation, which
can be used in for
loops or converted to an array or list.
Equations
- Std.RBMap.values t = t
Instances For
Equations
- Std.RBMap.instCoeHeadValuesArray = { coe := Std.RBMap.valuesArray }
Equations
- Std.RBMap.instCoeHeadValuesList = { coe := Std.RBMap.valuesList }
Equations
- One or more equations did not get rendered due to their size.
Equations
- Std.RBMap.instForMValues = { forM := fun [Monad m] (t : Std.RBMap.Values α β cmp) (f : β → m PUnit) => Std.RBNode.forM (fun (x : α × β) => f x.snd) t.val }
The result of toStream
on a Values
.
Equations
- Std.RBMap.Values.Stream α β = Std.RBNode.Stream (α × β)
Instances For
A stream over the iterator.
Equations
Instances For
O(1)
amortized, O(log n)
worst case: Get the next element from the stream.
Equations
- Std.RBMap.Values.Stream.next? t = match inline (Std.RBNode.Stream.next? t) with | none => none | some ((fst, b), t) => some (b, t)
Instances For
Equations
- Std.RBMap.instToStreamValuesStream = { toStream := Std.RBMap.Values.toStream }
Equations
- Std.RBMap.instStreamStream_1 = { next? := Std.RBMap.Values.Stream.next? }
Equations
- Std.RBMap.instReprRBMap = { reprPrec := fun (m : Std.RBMap α β cmp) (prec : Nat) => Repr.addAppParen (Std.Format.text "RBMap.ofList " ++ repr (Std.RBMap.toList m)) prec }
O(log n)
. Insert key-value pair (k, v)
into the tree.
Equations
- Std.RBMap.insert t k v = Std.RBSet.insert t (k, v)
Instances For
O(log n)
. Remove an element k
from the map.
Equations
- Std.RBMap.erase t k = Std.RBSet.erase t fun (x : α × β) => cmp k x.fst
Instances For
O(n log n)
. Build a tree from an unsorted list by inserting them one at a time.
Equations
- Std.RBMap.ofList l cmp = Std.RBSet.ofList l (Ordering.byKey Prod.fst cmp)
Instances For
O(n log n)
. Build a tree from an unsorted array by inserting them one at a time.
Equations
- Std.RBMap.ofArray l cmp = Std.RBSet.ofArray l (Ordering.byKey Prod.fst cmp)
Instances For
O(log n)
. Find an entry in the tree with key equal to k
.
Equations
- Std.RBMap.findEntry? t k = Std.RBSet.findP? t fun (x : α × β) => cmp k x.fst
Instances For
O(log n)
. Find the value corresponding to key k
.
Equations
- Std.RBMap.find? t k = Option.map (fun (x : α × β) => x.snd) (Std.RBMap.findEntry? t k)
Instances For
O(log n)
. Find the value corresponding to key k
, or return v₀
if it is not in the map.
Equations
- Std.RBMap.findD t k v₀ = Option.getD (Std.RBMap.find? t k) v₀
Instances For
O(log n)
. lowerBound? k
retrieves the key-value pair of the largest key
smaller than or equal to k
, if it exists.
Equations
- Std.RBMap.lowerBound? t k = Std.RBSet.lowerBoundP? t fun (x : α × β) => cmp k x.fst
Instances For
O(log n)
. Returns true if the given key a
is in the RBMap.
Equations
- Std.RBMap.contains t a = Option.isSome (Std.RBMap.findEntry? t a)
Instances For
O(n)
. Returns true if the given predicate is true for all items in the RBMap.
Equations
- Std.RBMap.all t p = Std.RBSet.all t fun (x : α × β) => match x with | (a, b) => p a b
Instances For
O(n)
. Returns true if the given predicate is true for any item in the RBMap.
Equations
- Std.RBMap.any t p = Std.RBSet.any t fun (x : α × β) => match x with | (a, b) => p a b
Instances For
Asserts that t₁
and t₂
have the same number of elements in the same order,
and R
holds pairwise between them. The tree structure is ignored.
Equations
- Std.RBMap.all₂ R t₁ t₂ = Std.RBSet.all₂ R t₁ t₂
Instances For
Asserts that t₁
and t₂
have the same set of keys (up to equality).
Equations
- Std.RBMap.eqKeys t₁ t₂ = Std.RBMap.all₂ (fun (x : α × β) (x_1 : α × γ) => decide (cmp x.fst x_1.fst = Ordering.eq)) t₁ t₂
Instances For
Returns true if t₁
and t₂
have the same keys and values
(assuming cmp
and ==
are compatible), ignoring the internal tree structure.
Equations
- Std.RBMap.instBEqRBMap = inferInstanceAs (BEq (Std.RBSet (α × β) (Ordering.byKey Prod.fst cmp)))
Attempts to find the value with key k : α
in t
and panics if there is no such key.
Equations
- Std.RBMap.find! t k = Option.getD (Std.RBMap.find? t k) (panicWithPosWithDecl "Std.Data.RBMap.Basic" "Std.RBMap.find!" 1081 20 "key is not in the map")
Instances For
O(n₂ * log (n₁ + n₂))
. Merges the maps t₁
and t₂
, if a key a : α
exists in both,
then use mergeFn a b₁ b₂
to produce the new merged value.
Equations
- One or more equations did not get rendered due to their size.
Instances For
O(n₁ * log (n₁ + n₂))
. Intersects the maps t₁
and t₂
using mergeFn a b
to produce the new value.
Equations
- One or more equations did not get rendered due to their size.
Instances For
O(n * log n)
. Constructs the set of all elements satisfying p
.
Equations
- Std.RBMap.filter t p = Std.RBSet.filter t fun (x : α × β) => match x with | (a, b) => p a b
Instances For
O(n₁ * (log n₁ + log n₂))
. Constructs the set of all elements of t₁
that are not in t₂
.
Equations
- Std.RBMap.sdiff t₁ t₂ = Std.RBMap.filter t₁ fun (a : α) (x : β) => !Std.RBMap.contains t₂ a
Instances For
O(n log n)
. Build a tree from an unsorted list by inserting them one at a time.
Equations
- List.toRBMap l cmp = Std.RBMap.ofList l cmp