Disjunkint set system

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 22. kesäkuuta 2017 tarkistetusta versiosta . tarkastukset vaativat 13 muokkausta .

Disjoint-set system ( eng.  disjoint-set tai union-find -tietorakenne ) on tietorakenne , jonka avulla voit hallita elementtijoukkoa, joka on jaettu disjoint-alijoukkoon. Tässä tapauksessa kullekin osajoukolle määritetään sen edustaja - tämän osajoukon elementti. Abstrakti tietorakenne määritellään kolmen toiminnon joukolla: .

Sitä käytetään yhdistettyjen komponenttien tallentamiseen kaavioihin , erityisesti Kruskalin algoritmi tarvitsee samanlaisen tietorakenteen tehokkaaseen toteutukseen.

Määritelmä

Olkoon äärellinen joukko, joka on jaettu ei-leikkaaviin osajoukkoon ( luokkiin ) :

.

Jokaiselle osajoukolle on määritetty edustaja . Vastaava disjunktijoukkojen järjestelmä tukee seuraavia toimintoja:

Algoritminen toteutus

Triviaali toteutus tallentaa hakemistotaulukon elementtien ja edustajien omistajuuden . Käytännössä puujoukkoja käytetään useammin . Tämä voi merkittävästi lyhentää Etsi -toiminnon aikaa . Tässä tapauksessa edustaja kirjoitetaan puun juureen ja luokan loput elementit sen alapuolella oleviin solmuihin.

Heuristiikka

Union-By-Size- , Union-By-Height- , Random -Union- heuristiikkaa ja polun pakkausta voidaan käyttää nopeuttamaan liitos- ja hakutoimintoja.

Union-By-Size -heuristisessa toimenpiteen aikana pienemmän puun juuri ripustetaan suuremman puun juuren alle. Tämä lähestymistapa säilyttää puun tasapainon. Kunkin alipuun syvyys ei voi olla suurempi kuin . Tätä heuristiikkaa käytettäessä pahimman mahdollisen Etsi -toiminnon aika kasvaa arvosta . Tehokkaan toteutuksen varmistamiseksi on ehdotettu, että puun solmujen lukumäärä tallennetaan juureen.

Union-By-Height -heuristiikka on samanlainen kuin Union-By-Size , mutta käyttää puun korkeutta koon sijaan.

Random-Union- heuristiikka käyttää sitä tosiasiaa, että on mahdollista olla käyttämättä lisämuistia puun solmujen määrän tallentamiseen: riittää, että valitaan juuri satunnaisesti - tämä ratkaisu antaa satunnaisille kyselyille nopeuden, joka on melko verrattavissa muihin. toteutukset. Jos kyselyitä, kuten "yhdistä suuri joukko pieneen", on kuitenkin useita, tämä heuristinen parantaa odotettua arvoa (eli keskimääräistä ajoaikaa) vain kaksinkertaiseksi, joten sen käyttöä ei suositella ilman polun pakkausheuristiikka.

Reitin pakkausheuristiikkaa käytetään nopeuttamaan toimintaa . Jokaisen uuden haun yhteydessä kaikki elementit, jotka ovat polulla juuresta haluttuun elementtiin, ripustetaan puun juuren alle. Tässä tapauksessa Etsi -toiminto toimii keskimäärin , missä on Ackerman-funktion  käänteisfunktio . Näin voit nopeuttaa työtä merkittävästi, koska kaikilla käytännössä käytetyillä arvoilla se vaatii alle 5:n.

Toteutusesimerkki

Toteutus C++:ssa:

const int MAXN = 1000 ; int p [ MAXN ], sijoitus [ MAXN ]; void MakeSet ( int x ) { p [ x ] = x ; sijoitus [ x ] = 0 ; } int Etsi ( int x ) { return ( x == p [ x ] ? x : p [ x ] = Etsi ( p [ x ]) ); } void Union ( int x , int y ) { if ( ( x = Etsi ( x )) == ( y = Etsi ( y )) ) paluu ; jos ( sijoitus [ x ] < sijoitus [ y ] ) p [ x ] = y ; else { p [ y ] = x ; jos ( sijoitus [ x ] == sijoitus [ y ] ) ++ sijoitus [ x ]; } }

Toteutus Free Pascalissa:

const MAX_N = 1000 ; var Parent , Rank : matriisi [ 1..MAX_N ] LongInt : stä ; _ proseduurin vaihto ( var x , y : LongInt ) ; var tmp : LongInt ; alkaa tmp := x ; x : = y y := tmp ; loppu ; menettely MakeSet ( x : LongInt ) ; alkaa Vanhempi [ x ] := x ; Sijoitus [ x ] := 0 ; loppu ; toiminto Etsi ( x : LongInt ) : LongInt ; alkaa jos ( Vanhempi [ x ] <> x ) sitten Vanhempi [ x ] := Etsi ( vanhempi [ x ] ) ; Poistu ( Parent [ x ] ) ; loppu ; menettely Unioni ( x , y : LongInt ) ; alkaa x := Etsi ( x ) ; y := Etsi ( y ) ; jos ( x = y ) sitten poistu () ; if ( Sijoitus [ x ] < Sijoitus [ y ] ) sitten swap ( x , y ) ; Vanhempi [ y ] := x ; if ( Sijoitus [ x ] = Sijoitus [ y ] ) sitten inc ( Sijainti [ x ] ) ; loppu ;

Katso myös

Kirjallisuus

Linkit