Disjunktna množica (union-find) sledi elementom, razdeljenim v neprekrivajočih se skupinah, in odgovarja na "sta ta dva v isti skupini?" in "združi dve skupini" v . Z in obe operaciji tečeta v — praktično O(1) (α je inverzna Ackermannova funkcija).
Disjunktna množica (union-find) sledi elementom, razdeljenim v neprekrivajočih se skupinah, in odgovarja na "sta ta dva v isti skupini?" in "združi dve skupini" v . Z in obe operaciji tečeta v — praktično O(1) (α je inverzna Ackermannova funkcija).
Vsaka množica je drevo; korjen je predstavnik množice. find hodi do korjena; union poveže en korjen pod drugega.
find(x): follow parents to the root
union(a,b): attach the shorter tree under the taller (by rank)
path compression: after find, point nodes DIRECTLY at the root
before: a->b->c->root after: a->root, b->root, c->root
class DSU:
def __init__(self, n):
self.parent = list(range(n))
self.rank = [0]*n
def find(self, x): # path compression
while self.parent[x] != x:
self.parent[x] = self.parent[self.parent[x]] # halve path
x = self.parent[x]
return x
def union(self, a, b): # union by rank
ra, rb = self.find(a), self.find(b)
if ra == rb: return False
if self.rank[ra] < self.rank[rb]: ra, rb = rb, ra
self.parent[rb] = ra
if self.rank[ra] == self.rank[rb]: self.rank[ra] += 1
return True
| Operacija | Čas (z obema optimizacijama) |
|---|---|
| find | O(α(n)) ≈ O(1) |
| union | O(α(n)) ≈ O(1) |
Union-find rešuje probleme združevanja in povezanosti, ki bi sicer potrebovali ponavljajoče se O(n) prehode grafov, in jih skrči na skoraj O(1) na poizvedbo.
Je osnovni pripomoček, kadar mora te postopoma združevati množice in preverjati povezanost — pogosta tema na seniorskih intervjujih.