Advanced Data Structures
Learn advanced data structures essential for competitive programming: Union-Find (Disjoint Set), balanced trees, and specialized structures for complex problem solving.
1. Union-Find (Disjoint Set)
Union-Find data structure for efficiently managing disjoint sets with path compression and union by rank optimizations.
Union-Find Implementation
#include <iostream>
#include <vector>
using namespace std;
class UnionFind {
private:
vector<int> parent, rank;
int components;
public:
UnionFind(int n) : parent(n), rank(n, 0), components(n) {
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]); // Path compression
}
return parent[x];
}
bool unite(int x, int y) {
int px = find(x), py = find(y);
if (px == py) return false;
// Union by rank
if (rank[px] < rank[py]) {
parent[px] = py;
} else if (rank[px] > rank[py]) {
parent[py] = px;
} else {
parent[py] = px;
rank[px]++;
}
components--;
return true;
}
bool connected(int x, int y) {
return find(x) == find(y);
}
int getComponents() {
return components;
}
};
int main() {
UnionFind uf(6);
cout << "Initial components: " << uf.getComponents() << endl;
uf.unite(0, 1);
uf.unite(2, 3);
uf.unite(4, 5);
cout << "After unions: " << uf.getComponents() << endl;
cout << "0 and 1 connected: " << uf.connected(0, 1) << endl;
cout << "0 and 2 connected: " << uf.connected(0, 2) << endl;
uf.unite(1, 2);
cout << "After uniting 1 and 2: " << uf.getComponents() << endl;
cout << "0 and 3 connected: " << uf.connected(0, 3) << endl;
return 0;
}Summary
- Union-Find: Efficient disjoint set operations with near O(1) amortized time
- Path Compression: Flattens tree structure for faster subsequent operations
- Union by Rank: Keeps trees balanced to maintain efficiency
- Applications: Kruskal's MST, connectivity problems, cycle detection