Implementation of Disjoint Sets
Published by
sanya sanya
Tradeoffs in Implementing Disjoint Sets ADT
Implementing the Disjoint Sets ADT involves making choices on how to perform the ‘MakeSet’, ‘Find’, and ‘Union’ operations efficiently. Different strategies come with different tradeoffs in terms of time complexity and space usage.
- Time Complexity: Some implementations prioritize fast ‘Find’ operations, making it quicker to find the representative element (parent) of a set, while other implementations focus on fast ‘Union’ operations, making it efficient to merge two sets into one.
- Space Complexity: Some implementations use additional data structures to store information about the sets, which might consume more memory but can lead to better performance in certain operations. Others try to minimize the use of extra memory at the cost of slightly slower operations.
- Ease of Implementation: Some strategies are easier to understand and implement than others, but they might not be the most efficient in terms of time or space.
Fast UNION Implementation (Slow FIND)
In this tradeoff, the ‘Union’ operation is prioritized to be fast, while the ‘Find’ operation may be relatively slow. To achieve this simply link one representative element (parent) to the other during the ‘Union’ operation. However, this approach can lead to a chain-like structure, making the ‘Find’ operation slow.
Fast UNION Implementations (Quick FIND): UNION by Size, UNION by Height (UNION by Rank)
These strategies have the 'Find' operation speed-optimized, making it simple to identify the set's representative element. The trade-off is that because of additional bookkeeping, the 'Union' operation could be a little slower. These tactics are frequently applied in practice:
- UNION by Size: Each set in this method has a size assigned to it, and the smaller set is combined with the larger set during the 'Union' process. This increases the effectiveness of 'Find' by limiting the height of the resulting tree. This tactic aids in achieving 'Find' and 'Union' time complexity that is roughly logarithmic.
- UNION by Height (UNION by Rank): According to this method, each set is assigned a height (also known as rank), and during the 'Union' process, the smaller of the two trees' heights is combined with the larger of the two trees' heights. Once more, this lowers the height and preserves the balance of the tree structure, making 'Find' operations more effective.
Comparing UNION by Size and UNION by Height
Both the UNION by Size and UNION by Height techniques seek to maintain a generally balanced forest, but they do it using various measures. During the 'Union' operation, UNION by Size guarantees that the larger tree becomes the parent and UNION by Height that the tree with the smaller height becomes the child.
As it keeps the trees from going too deep (and hence avoids long chains), UNION by Rank (Height) is typically slightly more effective than UNION by Size.
What is Path Compression?
Disjoint Sets employ the method of path compression to further enhance the 'Find' function. Path compression makes guarantee that all elements along the path from element 'x' to the root are immediately linked to the root when performing a 'Find' operation to locate the representative element of element 'x'.
In other words, each component of the path as you ascend the tree to the representative is "flattened" and joined to the root. By drastically lowering the height of the tree, this compression phase speeds up subsequent "Find" processes.
FIND with path compression
int find(int x) {
if (parent[x] != x)
parent[x] = find(parent[x]); // Path compression
return parent[x];
}
In this implementation, if ‘x’ is not the representative, we recursively perform ‘Find’ on its parent to find the true representative. Simultaneously, we compress the path by updating the parent of each element on the path directly to the root.
Path compression ensures that the tree becomes nearly flat, which leads to an amortized time complexity of approximately O(α(n)) for both the ‘Find’ and ‘Union’ operations, where α(n) is the inverse Ackermann function. This means that both ‘Find’ and ‘Union’ operations are very fast.
Comparsion of Various Implementation Methods
|Implementation Method|Advantages|Disadvantages| | :- | :- | :- | |Fast UNION (Slow FIND)|
Simple to implement.
Fast UNION operation.
|Slow FIND operation with potential long chains, resulting in O(n) worst-case time complexity for FIND.
Not suitable for large or complex disjoint sets.
| |Fast UNION (Quick FIND)|Efficient FIND operation with O(log n) average time complexity.
Suitable for larger disjoint sets.
|Slightly slower UNION operation due to additional bookkeeping for maintaining balanced trees.
Slightly more space usage to store additional information.
| |UNION by Size|Fast UNION operation.
Ensures the height of the resulting tree is at most O(log n), leading to efficient FIND.
|Requires additional space to store the size of each set.
The height can still grow linearly in rare cases, affecting FIND.
| |UNION by Height (Rank)|Efficient FIND operation with strict O(log n) height limit.
Can perform better than UNION by Size in practice.
|Slightly more space usage to store the rank (height) of each set.
Slightly more involved UNION operation for maintaining balanced trees.
| |Path Compression|Significant improvement in FIND operation, making it nearly constant time.|Slightly increases the overhead of FIND operation due to path traversal and updates of parent pointers.
Can be combined with any UNION strategy.
|Library
WEB DEVELOPMENT
FAANG QUESTIONS