[−][src]Struct red_union_find::UF
Implements union-find
The UF structure efficiently represents a disjoint set data structure.
The standard rust unsigned primitive types (u8
, u16
, u32
, u64
, u128
, and usize
)
make fine index types. You probably should use the smallest type that meets your needs.
UF can be viewed in a lattice. UF::new_reflexive() is the global infimum, and the result of
joining all elements with all other elements into one big equiovalence set is the global
supremum. equivalence_intersection()
is the lattice gcd, and equivalence_union()
is the
lattice lcm.
Implementations
impl<I> UF<I> where
I: Into<usize> + Copy + FromPrimitive,
[src]
I: Into<usize> + Copy + FromPrimitive,
pub fn new_reflexive(size: I) -> Self
[src]
Creates a minimal reflexive UF structure.
Each index i
is the sole memeber of its own equivalence set.
pub fn max(&self) -> I
[src]
Returns the element beyond the largest represented in ths UF
.
pub fn len(&self) -> usize
[src]
Number of indices in this UF
pub fn find(&self, i: I) -> I
[src]
Returns representative with minimum index from i
's equivalence set.
This method purports to immutably use &self
, but it really uses interior mutability to
implement path-compression in the safe, traditional way. Almost every other method on UF
delegates to find
, so they are all lying too. The data structure may be physically
changing, doing path compression, but these changes don't logically change the outcome of
any API calls.
Performance
If you perform n
find()
operations on a UF
with length len()
, then these operations
will take O(n
+ len()
) operations. So the performance is amortized O(1).
pub fn union(&mut self, i: I, j: I)
[src]
Perform union of two indices
Since UF
uses interior mutability, the mut
attribute here is not strictly necessary.
But it communicates to the user that the data structure is logically changing, so it's a
worthwhiile part of the API.
Performance
Each call to union
performs two find()
calls and additionally does O(1) work.
pub fn same_set(&self, i: I, j: I) -> bool
[src]
Retrns true if i
and j
are in the same equivalence set.
pub fn equivalence_union(a: &Self, b: &Self) -> Self
[src]
Creates a new UF that represents the union of the two given equivalence relations.
let c = UF::equivalence_union(&a, &b)
. Then for all i
and j
, c.same_set(i,j) == a.same_set(i,j) || b.same_set(i,j)
.
This operation is the lattice infimum over UF
.
Performance
O(len())
pub fn equivalence_intersection(a: &Self, b: &Self) -> Self
[src]
Creates a new UF that represents the intersection of the two given equivalence relations.
let c = UF::equivalence_intersection(&a, &b)
. Then for all i
and j
, c.same_set(i,j) == a.same_set(i,j) && b.same_set(i,j)
.
This operation is the lattice supremum over UF
.
You could also say this function returns the maximal mutual common ancestor of its
arguments. No sequence of union()
operations will transform a
or b
into c
, there
are sequences of union()
operations that will transform c
into either a
or b
, and a
minimal sequence of union()
operations for transforming c
to a
will have no entries
in common with a minimal sequence from c
to b
.
Performance
I have only been able to prove that the performance is somewhere between O(len()
) and
O(len()
^2). But it seems pretty fast.
If either a
or b
is mostly pure-reflexive or mostly one big equivalence set, or if a
and b
are very similar (each of them are a short number of unions away from their common
ancestor), then the performance is almost linear.
Creating the result can't be done in less than O(len()
) performace. The inner loop that
steps through the cycles can't do more than O(len()
^2) operations since it won't compare
the same two elements twice.
The worst case operation seems to be when there are large sets in both argument UF
s, but
the intersection has no non-reflexive elements. Imagine two UF's representing the
equivalence classes of two prime modular fields, based on primes p1 and p2. Then for large
len()
(larger than p1*p2
), this operation will take about O(len()*(p1+p2)
) operations.
pub fn as_permutation(&self) -> Vec<I>
[src]
Creates permutation version of a UF
Each equivalence set corresponds to a cycle. Every link in a cycle points downward, except for the smallest which points at the largest element in the cycle.
This representation can be used to do neat algorithmic things with an equivalence class.
pub fn leaders<'a>(&'a self) -> LeadersIter<'a, I>ⓘNotable traits for LeadersIter<'a, I>
impl<'a, I: Copy> Iterator for LeadersIter<'a, I> where
I: Into<usize> + Copy + FromPrimitive, type Item = I;
[src]
Notable traits for LeadersIter<'a, I>
impl<'a, I: Copy> Iterator for LeadersIter<'a, I> where
I: Into<usize> + Copy + FromPrimitive, type Item = I;
Returns an iterator over group leader indexes
Trait Implementations
impl<I: Clone + Copy> Clone for UF<I>
[src]
impl<I: Debug + Copy> Debug for UF<I>
[src]
impl<I> Eq for UF<I> where
I: Into<usize> + Copy + FromPrimitive + Eq,
[src]
I: Into<usize> + Copy + FromPrimitive + Eq,
impl<I> PartialEq<UF<I>> for UF<I> where
I: Into<usize> + Copy + FromPrimitive + PartialEq,
[src]
I: Into<usize> + Copy + FromPrimitive + PartialEq,
Auto Trait Implementations
impl<I> !RefUnwindSafe for UF<I>
impl<I> Send for UF<I> where
I: Send,
I: Send,
impl<I> !Sync for UF<I>
impl<I> Unpin for UF<I> where
I: Unpin,
I: Unpin,
impl<I> UnwindSafe for UF<I> where
I: UnwindSafe,
I: UnwindSafe,
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> ToOwned for T where
T: Clone,
[src]
T: Clone,
type Owned = T
The resulting type after obtaining ownership.
pub fn to_owned(&self) -> T
[src]
pub fn clone_into(&self, target: &mut T)
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,