Sistemul disjoint-set ( eng. disjoint -set , sau union-find data structure ) este o structură de date care vă permite să administrați un set de elemente, împărțit în subseturi disjunse. În acest caz, fiecărui subset i se atribuie reprezentantul său - un element al acestui subset. O structură abstractă de date este definită printr-un set de trei operații: .
Este folosit pentru a stoca componentele conectate în grafice , în special, algoritmul lui Kruskal are nevoie de o structură de date similară pentru o implementare eficientă.
Fie o mulțime finită împărțită în submulțimi care nu se intersectează ( clase ) :
.Fiecărui subset i se atribuie un reprezentant . Sistemul corespunzător de mulțimi disjunse suportă următoarele operații:
O implementare trivială stochează proprietatea elementelor și reprezentanților într-o matrice de index . În practică, seturile de copaci sunt mai des folosite . Acest lucru poate reduce semnificativ timpul necesar operației de căutare . În acest caz, reprezentantul este scris la rădăcina arborelui, iar elementele rămase ale clasei sunt scrise în nodurile de sub acesta.
Euristice Union-By-Size , Union-By-Height , Random-Union și compresia căilor pot fi utilizate pentru a accelera operațiunile Union și Find .
În euristica Union-By-Size , în timpul operației, rădăcina copacului mai mic este atârnată sub rădăcina copacului mai mare. Această abordare păstrează echilibrul copacului. Adâncimea fiecărui subarbore nu poate depăși . Folosind această euristică, timpul de operare Find în cel mai rău caz crește de la la . Pentru o implementare eficientă, se propune stocarea numărului de noduri din arbore la rădăcină.
Euristica Union-By-Height este similară cu Union-By-Size , dar folosește înălțimea arborelui în loc de dimensiune.
Euristica Random-Union folosește faptul că este posibil să nu cheltuiți memorie suplimentară pentru a salva numărul de noduri din arbore: este suficient să alegeți rădăcina în mod aleatoriu - această soluție oferă o viteză la interogările aleatoare care este destul de comparabilă cu alte implementari. Cu toate acestea, dacă există multe interogări precum „unește un set mare cu unul mic”, această euristică îmbunătățește valoarea așteptată (adică timpul mediu de rulare) cu doar un factor de doi, așa că nu este recomandat să-l folosești fără euristica de compresie a căii.
Euristica de compresie a căii este utilizată pentru a accelera operația . Cu fiecare nouă căutare, toate elementele care se află pe calea de la rădăcină la elementul dorit sunt atârnate sub rădăcina arborelui. În acest caz, operația Find va funcționa în medie , unde este funcția inversă a funcției Ackerman . Acest lucru vă permite să accelerați semnificativ munca, deoarece pentru toate valorile utilizate în practică este nevoie de o valoare mai mică de 5.
Implementare în C++:
const int MAXN = 1000 ; int p [ MAXN ], rang [ MAXN ]; void MakeSet ( int x ) { p [ x ] = x ; rang [ x ] = 0 ; } int Găsiți ( int x ) { return ( x == p [ x ] ? x : p [ x ] = Find ( p [ x ]) ); } void Uniune ( int x , int y ) { dacă ( ( x = Găsiți ( x )) == ( y = Găsiți ( y )) ) întoarcere ; dacă ( rang [ x ] < rang [ y ] ) p [ x ] = y ; else { p [ y ] = x ; dacă ( rang [ x ] == rang [ y ] ) ++ rang [ x ]; } }Implementare în Free Pascal:
const MAX_N = 1000 ; var Parent , Rank : matrice [ 1 .. MAX_N ] din LongInt ; procedura de schimbare ( var x , y : LongInt ) ; var tmp : LongInt ; ÎNCEPE tmp := x ; x : = y y := tmp ; sfârşitul ; procedura MakeSet ( x : LongInt ) ; ÎNCEPE Părinte [ x ] := x ; Rang [ x ] := 0 ; sfârşitul ; function Find ( x : LongInt ) : LongInt ; ÎNCEPE dacă ( Părinte [ x ] <> x ) atunci Părinte [ x ] := Găsiți ( Părinte [ x ] ) ; Ieșire ( Părinte [ x ] ) ; sfârşitul ; procedura Union ( x , y : LongInt ) ; ÎNCEPE x := Găsiți ( x ) ; y := Găsiți ( y ) ; if ( x = y ) atunci exit () ; dacă ( Rang [ x ] < Rang [ y ] ) atunci schimbă ( x , y ) ; Parinte [ y ] := x ; dacă ( Rang [ x ] = Rang [ y ] ) atunci inc ( Rang [ x ] ) ; sfârşitul ;Structuri de date | |
---|---|
Liste | |
Copaci | |
Contează | |
Alte |