Kruskal's algorithm (tsz. Kruskal's algorithms)
A Kruskal-algoritmus egy greedy módszer a minimális feszítőfa (Minimum Spanning Tree, MST) előállítására összefüggő, súlyozott, irányítatlan gráfokban. Célja, hogy az összes csúcsot lefedje úgy, hogy a kiválasztott élek súlyösszege minimális legyen, miközben körök (ciklusok) létrejöttét elkerüli.
2. Az algoritmus ötlete
Find(u) != Find(v)
, akkor az él nem zár ciklust ⇒ felvesszük az MST-be, és Union(u,v)
-vel egyesítjük a komponenseket.Az iteráció addig tart, míg az MST-ben él nem gyűlt össze (ahol a csúcsok száma).
3. Pseudokód
Kruskal(G, w): // G = (V, E) összefüggő, súlyozott, irányítatlan gráf T = ∅ // az MST éleinek halmaza rendezd növekvően E-t w szerint inicializáld a disjoint-setet V elemekkel for minden (u, v) ∈ E, súly szerint: if Find(u) ≠ Find(v): T = T ∪ {(u, v)} Union(u, v) if |T| == |V| - 1: break return T
4. Idő- és helykomplexitás
Élsorrendezés: . Mivel általában nagyobb, ezt tekintjük dominánsnak.
Disjoint-set műveletek: Ha útösszevonással (union by rank) és útkompresszióval (path compression) valósítjuk meg, akkor egy Find
vagy Union
amortizált , ahol az inverz Ackermann-függvény (gyakorlatilag konstans). Összesen legfeljebb Find
és Union
hívás ⇒ .
Összesen:
Helyigény:
5. Példa Legyen a következő gráf élekkel és súlyokkal:
1 4 A ——— B ——— C | \ | 2 3 5 | \ | D ———— E 6
Élek:
(A,B)=1, (A,D)=2, (A,E)=3, (B,C)=4, (B,E)=5, (D,E)=6
Rendezés súly szerint:
Disjoint-set inicializálás: minden csúcs külön komponens.
Élek feldolgozása:
(A,B)=1: külön komponens ⇒ felvesszük, egyesítjük A és B.
(A,D)=2: A és D külön ⇒ felvesszük, egyesítjük.
(A,E)=3: A (és B, D) külön E-től ⇒ felvesszük, egyesítjük.
(B,C)=4: B (koalícióban A,D,E) külön C-től ⇒ felvesszük, egyesítjük.
Ezt követően már él gyűlt össze, MST kész:
Az élek (B,E) és (D,E) kimaradnak, mert egységkomponensekbe esnének.
6. Python-implementáció
class DisjointSet:
def __init__(self, vertices):
self.parent = {v: v for v in vertices}
self.rank = {v: 0 for v in vertices}
def find(self, v):
if self.parent != v:
self.parent = self.find(self.parent)
return self.parent
def union(self, u, v):
ru, rv = self.find(u), self.find(v)
if ru == rv:
return
# union by rank
if self.rank < self.rank:
self.parent = rv
elif self.rank > self.rank:
self.parent = ru
else:
self.parent = ru
self.rank += 1
def kruskal(vertices, edges):
"""
vertices: iterable csúcsok
edges: lista
visszatér: lista az MST élekkel (u, v, w)
"""
# 1. rendezés
edges = sorted(edges, key=lambda x: x)
ds = DisjointSet(vertices)
mst =
# 2. élek hozzáadása
for u, v, w in edges:
if ds.find(u) != ds.find(v):
ds.union(u, v)
mst.append((u, v, w))
if len(mst) == len(vertices) - 1:
break
return mst
# Példa használat
verts =
eds = [
('A','B',1), ('A','D',2), ('A','E',3),
('B','C',4), ('B','E',5), ('D','E',6)
]
print("MST:", kruskal(verts, eds))
7. Alkalmazások
8. Összefoglalás A Kruskal-algoritmus egyszerű, de hatékony girbegurba eljárás a minimális feszítőfa megtalálására. A kulcs a súly szerinti élsorrendezés és a disjoint-set adatszerkezet használata a ciklusok elkerüléséhez. időkomplexitása miatt széles körben alkalmazható mérsékelt és nagy méretű gráfokban.