Skip to content

49 add union find data structure#62

Open
c-m-elliott wants to merge 86 commits into
mainfrom
49-add-union-find-data-structure
Open

49 add union find data structure#62
c-m-elliott wants to merge 86 commits into
mainfrom
49-add-union-find-data-structure

Conversation

@c-m-elliott

Copy link
Copy Markdown

So far, this includes the interfaces UnionFind, SortedUnionFind, PersistentUnionFind and PersistentSortedUnionFind as well as the abstract classes AbstractImmutableUnionFind and AbstractImmutableSortedUnionFind. It also contains a naive implementation of SortedUnionFind based on a HashMap of TreeSets (SortedTreeSetUnionFind). There is a set of tests (SortedUnionFindTest), but there seems to be some kind of problem regarding null values which is causing the JDK21 PackageSanityTest to fail. This in particular is something I'd appreciate input on. Thanks!

Colleen added 30 commits May 25, 2026 13:52
… mismatches that will be sorted out later on if I decide to stick with HashMaps
…) as static method problematic due to variable type
@baierd

baierd commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

TODO (WIP): make a concrete list of all things that we expect this PR to have with some examples (e.g. some interesting test-cases). Smaller work-packages are preferred.

List of wants and goals for this MR

Union-Find commonly only defines two methods:

  • the find() method. It has a single argument and returns the representative member of the set of elements that the argument belongs to.
  • the union() method. It takes two arguments, merging the two sets that each argument belongs to. In mutable data-structures the return type is void. Persistent and immutable versions deprecate this call. Persistent implementations add a new method unionAndCopy() returning a new copy of the initial Union-Find, with the two sets merged. The initial data-structure of the persistent implementation is unchanged after returning the new modified copy.

Another method getAllSets() or getAllSubSets() returning a set of all sets inside the Union-Find might be helpful and should also be added.

We should discuss whether we want size method(s), e.g. for the amount of sets or elements in all sets.

Sometimes a addition method is used, but i don't see any benefit for this, so we will not add it.

Interfaces (or abstract classes)

  • Interface for mutable Union-Find
  • Interface for ordered mutable Union-Find based on the interface for mutable Union-Find.
  • Interface for immutable Union-Find based on the interface of mutable Union-Find.
  • Interface for ordered immutable Union-Find based on the interfaces of immutable Union-Find and ordered Union-Find. Should multi-inheritance be a problem, you can switch out one of the 2 source interfaces for an abstract class. Ordered mutable Union-Find seems to be the better choice for this at a first glance, but you can evaluate this for yourself.
  • Interface for persistent Union-Find based on the interface for immutable Union-Find.
  • Interface for ordered persistent Union-Find based on the interface for persistent Union-Find and ordered immutable Union-Find. (See ordered immutable Union-Find above for the multi-inheritance problem you might face.)

Implementations

  • Mutable Union-Find
  • Immutable Union-Find
  • Persistent Union-Find

Union-Find data-structures are usually based on trees and can be implemented using commonly existing implementations (e.g. our PathCopyingPersistentTreeMap that is based on a RB-Tree). The problem is, these can not be optimized with the techniques below. A optimized tree for Union-Find needs to be a Parent-Pointer-Tree, i.e. a tree with its nodes storing only a single pointer towards their parents.

It makes sense to start with a "simple" implementation first, e.g. based on our PathCopyingPersistentTreeMap and/or a naive parent-pointer-tree without optimizations. This would also allow us to evaluation more optimized versions against naive implementations later on!

  • Ordered mutable Union-Find
  • Ordered immutable Union-Find
  • Ordered persistent Union-Find

Ordered parent-pointer-tree implementations seem to require a proper merge of the trees in most cases. It makes sense to focus on the unordered variants first. TODO: investigate further.

Note: a "unordered" data-structure implementation can sometimes be derived from an ordered. An example of this is our PathCopyingPersistentTreeMap, which is always ordered.

Tests

  • Mutable Union-Find tests. This should test the behavior for Union-Find. For example:
    • TODO: add examples
  • Ordered mutable Union-Find tests. Extend the mutable Union-Find tests by tests for the new API and ordering.
  • Immutable Union-Find tests. Simply translate the tests of mutable Union-Find to this.
  • Ordered immutable Union-Find tests. Similar to ordered mutable Union-Find tests.
  • Persistent Union-Find tests. Simply translate the tests of (im)mutable Union-Find to this.
  • Ordered persistent Union-Find tests. Similar to ordered mutable Union-Find tests.

I advice to "extend" tests only by the new features introduced in each implementation, and re-use existing tests as far as possible. E.g. ordered Union-Find test classes can just extend their unordered test-classes.

Documentation

TODO

(Runtime) Optimization

  • Path Compression (Path compression links set members to their root, making find operations more efficient.)
  • union by rank. This requires a background tree that stores its rank (i.e. the tree heights upper bound) in each root.
  • union by size. This requires a size-weighted tree as the background data-structure.

Our goal is to use at least one union optimization together with path compression. This should lead to a Union-Find implementation that is close to the best worst case time complexities possible if both are used. For find, the best possible worst-case time-complexity in this case is O(log n / log log n​), while union remains O(α(n)) (amortized).

Space complexity is usually O(n) and does not need to be optimized.

Evaluation

TODO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

Add Union-Find Data-Structure

2 participants