Disjoint-set system ( eng. disjoint-set , eller union-find data structure ) er en datastruktur, der giver dig mulighed for at administrere et sæt elementer, opdelt i usammenhængende delmængder. I dette tilfælde tildeles hver delmængde sin repræsentant - et element i denne delmængde. En abstrakt datastruktur er defineret af et sæt af tre operationer: .
Den bruges til at gemme tilsluttede komponenter i grafer , især Kruskals algoritme har brug for en lignende datastruktur for effektiv implementering.
Lad en endelig mængde opdelt i ikke-skærende delmængder ( klasser ) :
.Hver delmængde tildeles en repræsentant . Det tilsvarende system af usammenhængende sæt understøtter følgende operationer:
En triviel implementering gemmer ejerskabet af elementer fra og repræsentanter i et indeksarray . I praksis bruges træsæt oftere . Dette kan reducere den tid, der kræves til Find -operationen betydeligt . I dette tilfælde skrives repræsentanten til roden af træet, og de resterende elementer i klassen skrives til noderne under den.
Union-By-Size , Union-By-Height , Random-Union heuristik og stikomprimering kan bruges til at fremskynde Union og Find -operationer.
I Union-By-Size heuristikken bliver roden af det mindre træ under operationen hængt under roden af det større træ. Denne tilgang bevarer træets balance. Dybden af hvert undertræ må ikke overstige . Ved at bruge denne heuristik øges den værst tænkelige Find -operationstid fra til . For en effektiv implementering foreslås det at gemme antallet af noder i træet ved roden.
Heuristikken Union-By-Height ligner Union-By-Size , men bruger træets højde i stedet for størrelsen.
Random-Union- heuristikken bruger det faktum, at det er muligt ikke at bruge yderligere hukommelse på at gemme antallet af noder i træet: det er nok at vælge roden tilfældigt - denne løsning giver en hastighed på tilfældige forespørgsler, der er ret sammenlignelig med andre implementeringer. Men hvis der er mange forespørgsler som "flet et stort sæt med et lille", forbedrer denne heuristik den forventede værdi (det vil sige den gennemsnitlige køretid) med kun en faktor to, så det anbefales ikke at bruge det uden banekomprimeringsheuristikken.
Stikomprimeringsheuristikken bruges til at fremskynde operationen . Ved hver ny søgning bliver alle elementer, der er på stien fra roden til det ønskede element, hængt under træets rod. I dette tilfælde vil Find -operationen fungere i gennemsnit , hvor er den omvendte funktion af Ackerman-funktionen . Dette giver dig mulighed for at fremskynde arbejdet betydeligt, da det for alle værdier, der bruges i praksis, tager en værdi mindre end 5.
Implementering i C++:
const int MAXN = 1000 ; int p [ MAXN ], rang [ MAXN ]; void MakeSet ( int x ) { p [ x ] = x ; rang [ x ] = 0 ; } int Find ( int x ) { return ( x == p [ x ] ? x : p [ x ] = Find ( p [ x ]) ); } void Union ( int x , int y ) { if ( ( x = Find ( x )) == ( y = Find ( y )) ) returnere ; hvis ( rang [ x ] < rang [ y ] ) p [ x ] = y ; andet { p [ y ] = x ; if ( rang [ x ] == rang [ y ] ) ++ rang [ x ]; } }Implementering i Free Pascal:
const MAX_N = 1000 ; var Parent , Rank : array [ 1..MAX_N ] af LongInt ; _ _ procedure swap ( var x , y : LongInt ) ; var tmp : LongInt ; begynde tmp := x ; x : = y y := tmp ; ende ; procedure MakeSet ( x : LongInt ) ; begynde Forælder [ x ] := x ; Rang [ x ] := 0 ; ende ; function Find ( x : LongInt ) : LongInt ; begynde hvis ( Forælder [ x ] <> x ) så Forælder [ x ] := Find ( Forælder [ x ] ) ; Afslut ( forælder [ x ] ) ; ende ; procedure Union ( x , y : LongInt ) ; begynde x := Find ( x ) ; y := Find ( y ) ; hvis ( x = y ) så afslut () ; hvis ( Ranger [ x ] < Ranger [ y ] ) så swap ( x , y ) ; Forælder [ y ] := x ; hvis ( Rank [ x ] = Rang [ y ] ) derefter inc ( Rang [ x ] ) ; ende ;Datastrukturer | |
---|---|
Lister | |
Træer | |
Tæller | |
Andet |