Improve complexity of union_find, better explain complexity.

Summary:
Old union find implementation was not true about it's complexity.
Take a look at http://www.brpreiss.com/books/opus4/html/page411.html#theoremsetsi.

Test Plan: Run union_find in tests.

Reviewers: mislav.bradac, buda

Reviewed By: mislav.bradac

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D51
This commit is contained in:
Dominik Gleich 2017-02-20 18:50:59 +01:00
parent 2cee2cf480
commit 40aa500a88

View File

@ -6,7 +6,7 @@
template <class uintXX_t = uint32_t> template <class uintXX_t = uint32_t>
/** /**
* UnionFind data structure. Provides means of connectivity * UnionFind data structure. Provides means of connectivity
* setting and checking in logarithmic complexity. Memory * setting and checking in O(alpha(n)) amortized complexity. Memory
* complexity is linear. * complexity is linear.
*/ */
class UnionFind { class UnionFind {
@ -16,15 +16,15 @@ class UnionFind {
* *
* @param n Number of elements in the data structure. * @param n Number of elements in the data structure.
*/ */
UnionFind(uintXX_t n) : set_count(n), count(n), parent(n) { UnionFind(uintXX_t n) : set_count(n), rank(n), parent(n) {
for (auto i = 0; i < n; ++i) count[i] = 1, parent[i] = i; for (auto i = 0; i < n; ++i) rank[i] = 0, parent[i] = i;
} }
/** /**
* Connects two elements (and thereby the sets they belong * Connects two elements (and thereby the sets they belong
* to). If they are already connected the function has no effect. * to). If they are already connected the function has no effect.
* *
* Has O(alpha(n)) time complexity. * Has O(alpha(n)) amortized time complexity.
* *
* @param p First element. * @param p First element.
* @param q Second element. * @param q Second element.
@ -36,18 +36,21 @@ class UnionFind {
// if roots are equal, we don't have to do anything // if roots are equal, we don't have to do anything
if (rp == rq) return; if (rp == rq) return;
// merge the smaller subtree to the root of the larger subtree // merge the subtree with the smaller rank to the root of the subtree with
if (count[rp] < count[rq]) // the larger rank
parent[rp] = rq, count[rp] += count[rp]; if (rank[rp] < rank[rq])
parent[rp] = rq;
else if (rank[rp] > rank[rq])
parent[rq] = rp;
else else
parent[rq] = rp, count[rp] += count[rq]; parent[rq] = rp, rank[rp] += 1;
// update the number of groups // update the number of groups
set_count--; set_count--;
} }
/** /**
* Indicates if two elements are connected. Has O(alpha(n)) time * Indicates if two elements are connected. Has amortized O(alpha(n)) time
* complexity. * complexity.
* *
* @param p First element. * @param p First element.
@ -66,8 +69,8 @@ class UnionFind {
private: private:
uintXX_t set_count; uintXX_t set_count;
// array of subtree counts // array of subtree ranks
std::vector<uintXX_t> count; std::vector<uintXX_t> rank;
// array of tree indices // array of tree indices
std::vector<uintXX_t> parent; std::vector<uintXX_t> parent;