9. Graafit Graafeilla eli verkoilla esitetään yhteystietoja. Esimerkkejä niistä ovat kaupunkikartan kadut ja tietoverkon tietokoneet. Tämä luku tarkastelee verkkojen perusasioita. 9.1. Graafin abstrakti tietotyyppi Abstraktissa mielessä graafi (graph) G on yksinkertaisesti kärkien (vertices) eli solmujen (nodes) joukko V ja solmuparien eli kaarien eli särmien (arcs, edges) joukko E. 9. luku 453
Termejä ja perusominaisuuksia Graafin kaaret ovat joko suunnattuja (directed) tai suuntaamattomia (undirected). Kaari (u,v) on suunnattu solmusta u solmuun v, jos pari (u,v) on järjestetty u:n edeltäessä v:tä. Jos järjestystä ei ole määritelty, kaari on suuntaamaton, jolloin (u,v) on sama kuin (v,u). Esim. 9.1. Katsotaan graafia, joka kuvaa kurssin lähdeteoksen kirjoittajien yhteistyöntekijöitä tutkimuksessa. Kaaret ovat symmetrisiä (symmetric), sillä jos A on tehnyt yhteistyötä B:n kanssa, niin asia on myös toisinpäin (kuva 9.1.). 9. luku 454
Snoeyink Garg Tollis Goodrich Tamassia Vitter Preparata Chiang Kuva 9.1. Graafi yhteistyöntekijöiden välillä. 9. luku 455
Jos kaikki graafin kaaret ovat suuntaamattomia, puhutaan suuntaamattomasta graafista (undirected graph). Vastaavasti suunnatussa graafissa (directed graph, digraph) kaikki kaaret ovat suunnattuja. On myös sekamuotoisia (mixed) graafeja, joissa esiintyy molempia tyyppejä kaaria. Suuntaamaton kaari (u,v) voidaan korvata parilla suunnattuja (u,v) ja (v,u). Kaaren yhdistämät kaksi solmua ovat sen päätesolmut tai kärjet (endpoints, end vertices). Jos se on suunnattu, toinen niistä on alku (origin) ja toinen loppu (destination). Kaksi solmua ovat vierekkäisiä (adjacent), jos ne ovat saman kaaren päätesolmuja. Kaari on solmuun liittyvä tai kuuluva (incident), jos solmu on kaaren alku tai loppu. Solmun v ulkoaste outdeg(v) (outdegree) on siitä lähtevien suunnattujen kaarien lukumäärä ja sisäaste indeg(v) (in degree) siihen tulevien suunnattujen kaarien lukumäärä. Solmun v aste deg(v) (degree) on solmuun yhteydessä olevien kaarien määrä eli samalla sen vierekkäisten solmujen määrä. 9. luku 456
Esim. 9.2. Lentoreiteistä voidaan muodostaa graafi G, jonka solmut viittaavat lentokenttiin ja kaaret ovat niihin liittyviä lentovuoroja (kuva 9.2.). Kaaret ovat luonnollisesti suunnattuja, koska lennolla on aina määrätty suunta lähtöpaikasta kohteeseen. Kaksi lentokenttää ovat vierekkäisiä graafissa, jos niiden välillä on lentovuoro. Solmun v sisäaste on kyseiselle lentokentälle saapuvat lennot ja sen ulkoaste siitä lähtevät lennot. Graafin määritelmä viittaa kaarien osalta pikemmin niiden kokoelmaan kuin joukkoon sallien kahdella suuntaamattomalla kaarella olevan samat päätesolmut sekä kahdella suunnatulla kaarella olevan sama alkusolmu ja toisaalta sama loppusolmu. Tällaisia kaaria kutsutaan rinnakkaisiksi (parallel edges) tai monikaariksi (multiple edges). Esim 9.2. voisi sisältää näitä, kun kahden lentokentän välillä olisi useita lentovuoroja eri aikoihin. Eräs toinen erikoistapaus on kaari, joka yhdistää solmun itseensä. Tästä käytetään nimitystä itseissilmukka (self loop). 9. luku 457
SFO LAX AA 49 UA 877 UA 120 TW 45 ORD DL 335 DFW AA 411 AA 1387 AA 523 JFK AA 903 MIA BOS NW 35 DL 247 Kuva 9.2. Esimerkki suunnatusta graafista, joka esittää lentoreitistöä. Kaaren UA 120 alku ja loppusolmu ovat LAX ja ORD. LAX ja ORD ovat täten vierekkäisiä. Solmun DFW sisäaste on 3 ja ulkoaste 2. 9. luku 458
Yleensä graafeissa ei ole rinnakkaisia kaaria tai itseissilmukoita, jotka ovat poikkeuksellisia. Jos niitä ei esiinny, graafin sanotaan olevan yksinkertainen (simple), mikä yksinkertaistaa graafien tietorakenteiden ja algoritmien esitystä. Tällöin yksinkertaisen graafin kaaret muodostavat solmuparien joukon (set) eikä vain kokoelmaa. Tässä luvussa oletetaan tilanteen olevan tämä ellei toisin mainita. Esitettävien määritelmien laajentaminen erityistapausten huomioonottamiseksi olisi suoraviivaista, mutta jonkin verran työlästä. Oheiset ominaisuudet esittävät graafin kaarien ja solmujen määrien suhteet sekä solmujen asteet. Lause 9.1. Jos graafissa G on m kaarta, niin on v G deg( v ) = 2m. 9. luku 459
Perustelu: Kaari (u,v) lasketaan kahdesti esitetyssä summassa, kerran loppusolmunaan u ja toisen kerran loppusolmunaan v. Näin ollen kaarien kokonaisvaikutus solmujen asteisiin on kaksi kertaa kaarien määrä. Lause 9.2. Jos suunnatussa graafissa G on m kaarta, niin on v G in deg( v ) = outdeg( v) = m. v G Perustelu: Suunnatussa graafissa kaari (u,v) vaikuttaa yhden yksikön verran alkusolmun u ulkoasteeseen ja yhden yksikön verran loppusolmun v sisäasteeseen. Niinpä kaarten kokonaisvaikutus solmujen ulkoasteisiin on yhtä kuin kaarten lukumäärä ja samoin on sisäasteilla. 9. luku 460
Lause 9.3. Olkoon G yksinkertainen graafi, jossa on n solmua ja m kaarta. Jos G on suuntaamaton, niin on m n(n 1)/2, ja jos G on suunnattu, niin on m n(n 1). Perustelu: Suuntaamattomassa graafissa ei millään kahdella kaarella voi olla samoja päätesolmuja eikä ole itseissilmukoita. Tällöin graafin solmun maksimiaste on n 1. Täten lauseen 9.1. mukaan on 2m n(n 1). Suunnatussa graafissa ei millään kahdella kaarella voi olla samaa alkusolmua ja samaa loppusolmua eikä ole itseissilmukoita. Tällöin graafin solmun maksimisisäaste on n 1. Lauseen 9.2. mukaan on m n(n 1). Lauseen 9.3. tulema on esitettävissä myös muodossa, että n solmuisella yksinkertaisella graafilla on O(n 2 ) kaarta. Graafin polku (path) on vuorottelevien solmujen ja kaarien sekvenssi, joka alkaa solmusta ja päättyy solmuun siten, että jokainen kaari liittyy edeltäjä ja seuraajasolmuunsa. Sykli (cycle) on polku, joka alkaa ja loppuu samaan solmuun. 9. luku 461
Polku on yksinkertainen (simple), jos sen solmut ovat erillisiä. Sykli on yksinkertainen (simple), jos sen solmut ovat erillisiä ensimmäistä ja viimeistä lukuunottamatta. Suunnatulla polulla (directed path) kaikki kaaret ovat suunnattuja ja kuljetaan läpi niiden suunnissa, ja suunnatusssa syklissä (directed cycle) määritellään samoin. Esim. 9.2. tapauksessa (BOS, NW 35, JFK, AA 1387, DFW) on suunnattu yksinkertainen polku ja (LAX, UA 120, ORD, UA 877, DFW, AA 49, LAX) on suunnattu yksinkertainen sykli. Graafin G aligraafi (subgraph) on graafi H, jonka solmut ja kaaret ovat graafin G solmujen ja kaarten osajoukkoja. Esim. 9.2. tapauksessa solmut BOS, JFK ja MIA sekä kaaret AA 903 ja DL 247 muodostavat aligraafin. Virittävä aligraafi (spanning subgraph) on graafin G aligraafi, joka käsittää G:n kaikki solmut. Graafi on yhdistetty (connected), jos minkä tahansa solmuparin välillä on polku. Jos graafi ei ole yhdistetty, sen maksimaalisia yhdistettyjä aligraafeja kutsutaan G:n yhdistetyiksi komponenteiksi (connected components). 9. luku 462
Metsä (forest) on syklitön graafi. Puu (tree) on yhdistetty metsä eli yhdistetty syklitön graafi. Tämä puun määritelmä on hieman erilainen kuin luvussa 4, koska graafin tilanteessa ei määritelty juurta. Näiden erottamiseksi toisistaan voidaan luvun 4 puu nimetä juurelliseksi puuksi (rooted tree). Metsän yhdistetyt komponentit ovat (vapaita) puita. Graafin virittävä puu (spanning tree) on virittävä aligraafi, joka on (vapaa) puu. Em. määritteiden ominaisuuksia luetellaan seuraavassa. Lause 9.4. Kun suuntaamattomassa graafissa G on n solmua ja m kaarta, niin mainittavat ominaisuudet ovat (perustelu voi olla harjoituksena): Jos G on yhdistetty, niin on m n 1. Jos G on puu, niin on m = n 1. Jos G on metsä, niin on m n 1. 9. luku 463
Graafin metodit Abstraktissa tietotyypissä graafin paikat (positions) ovat sen solmut ja kaaret. Graafin alkiot voidaan näin ollen tallettaa joko solmuihin tai kaariin (tai molempiin). Graafi nähdään paikkasäiliönä (luku 4), jolloin graafin abstrakti tietotyyppi tukee metodeja size(), isempty(), elements(), positions(), replace(p,o) ja swap(p,q), missä p ja q viittaavat paikkoihin ja o alkioon. Graafit ovat hyvin monipuolisia rakenteita johtuen niiden erilaisista rakenneosista, solmuista ja kaarista. Graafien metodit jaotellaan kolmeen ryhmään: yleismetodit, suunnattuja kaaria käsittelevät metodit ja graafien päivitys ja muuntamismetodit. Olkoot v solmu, e kaari ja o solmuun tai kaareen talletettu alkio. Seuraavassa esitetään esimerkinomaisesti vain muutamia metodeja, joita voi kehittää lisää monia kymmeniä. Myöskään niiden virheenkäsittelyä ei tarkastella. 9. luku 464
Yleismetodeissa ei piitata kaarien suunnista. Ne antavat globaalia tietoa graafista. numvertices(): edges(): Palauttaa G:n solmujen lukumäärän. Palauttaa G:n kaarien luettelon. Seuraavantyyppisissä yleismetodeissa on solmuja ja kaaria argumentteina. degrees(v): Palauttaa solmun v asteen. endvertices(e): Palauttaa kaaren e päätesolmut. areadjacent(v,w): Palauttaa totuusarvon sen mukaan, ovatko v ja w vierekkäisiä solmuja. Kun otetaan huomioon kaarien suuntia, monia erilaisia metodeja on esitettävissä. indegree(v): Palauttaa solmun v sisäasteen. 9. luku 465
inadjacentvertices(v): Palauttaa luettelon kaikista solmulle v vierekkäisistä solmuista, jotka tulevat suunnattuja kaaria myöten v:hen. destination(e): Palauttaa suunnatun kaaren e loppusolmun. Päivitysmetodeilla voidaan lisätä tai poistaa kaaria ja solmuja. insertedge(v,w,o): Lisää ja palauttaa suuntaamattoman kaaren solmujen v ja w välistä sekä tallettaa alkion o tähän paikkaan. removevertex(v): Poistaa solmun v ja kaikki siihen liittyvät kaaret. Kuten mainittu, tässä esitettiin ainoastaan muutamia esimerkkejä lukuisista mahdollisista graafimetodeista. (Ne luetellaan tätä täydellisimmin myöhemmissä taulukoissa.) 9. luku 466
9.2. Graafien tietorakennetoteutukset Graafin abstrakti tietotyyppi toteutetaan yleensä yhtenä kolmesta vaihtoehdosta. Nämä rakenteet ovat kaarilista (edge list), vierekkyyslista (adjacency list) ja vierekkyysmatriisi (adjacency matrix). Kun näistä kaksi ensimmäistä sisältävät pelkästään tiedon jostakin solmusta ja kaaresta, niiden tarvitsema muistitila on O(n+m), missä n on solmujen ja m kaarien lukumäärät. Kolmas rakennevaihtoehto tarvitsee tilaa O(n 2 ), koska siinä varataan tilaa jokaiselle solmuparille riippumatta siitä, onko niiden välillä kaarta vai ei. Kaarilistarakenne Kaarilista on yksinkertaisin, mutta ei tehokkain graafin esitysmuoto. Solmu v tallettaa alkion o, mikä on eksplisiittisesti esitetty toteutuksen solmuoliossa. 9. luku 467
Kaikki solmuoliot talletetaan säiliöön V, joka on tavallisesti sekvenssi tai sanakirja. Jos sovelletaan järjestettyä sekvenssiä, solmuille annetaan järjestysnumero. Sanakirjan tapauksessa ne merkitään avaimilla. Solmun v solmuoliolla, jossa on alkio o talletettuna, on seuraavat tiedot sisältävät muuttujat : viittaus alkioon o solmuun liittyvien suuntaamattomien kaarien määrä, sisäaste ja ulkoaste viittaus solmuolion paikkaan säiliössä V Alkion o sisältävä kaari e esitetään eksplisiittisesti kaarioliolla. Kaarioliot talletetaan säiliöön E, joka on sekvenssi tai sanakirja. Kaarioliolla on seuraavat muuttujat: 9. luku 468
viittaus alkioon o Boolen muuttuja sille, onko kaari e suuntaamaton tai suunnattu viittaukset säiliön V solmuolioihin, jotka liittyvät kaaren e päätesolmuihin (e suuntaamaton) tai sen alku ja loppusolmuun (e suunnattu) viittaus kaariolion paikkaan säiliössä E Kaarilistasta on kuvassa 9.3. kaavamainen esitys. Kaarilistasta puhutaan, koska sen toteutus on usein sekvenssi (listana). Kaarilistarakenteen pääpiirre on suora haku kaarista näihin liittyviin solmuihin. Tämä tuottaa yksinkertaisia algoritmeja kaarien käsittelyyn. Sen sijaan käänteinen toiminto, solmuun liittyvien kaarien saanti, vaatii täydellisen haun kaarien säiliössä E. Näin ollen mm. metodi incidentedges(v) toimii ajassa, joka on suhteessa kaarien määrään (eikä solmujen). Taulukossa 9.1. on lueteltu tärkeimpien metodien suoritusajat, joiden perusteluja ei tässä tarkastella. 9. luku 469
SFO LAX AA 49 UA 877 UA 120 TW 45 ORD DFW AA 411 (a) DL 335 AA 1387 AA 523 JFK AA 903 MIA BOS NW 35 DL 247 Kuva 9.3. (alku) (a) Suunnattu graafi G kuvasta 9.2. 9. luku 470
E: NW 35 DL 247 AA 49 DL 335 AA1387 AA 523 AA 411 UA 120 AA 903 UA 877 TW 45 V: BOS LAX DFW JFK MIA ORD SFO (b) Kuva 9.3. (loppu) (b) Graafin G kaavamainen esitys kaarilistana. Selvyyden vuoksi viittaukset on tässä merkitty olioiden nimillä (eikä merkitty viittauksia nuolien yhteyteen). 9. luku 471
Taulukko 9.1. Graafimetodien suoritusajat, kun toteutus on kaarilistana, missä V ja E on toteutettu kahteen suuntaan linkitettyjen listojen sekvensseinä. Tilavaatimus on O(n+m), missä n on solmujen lukumäärä ja m kaarien lukumäärä. operaatio size, isempty, replaceelement, swap numvertice, numedges vertices edges, directededges, undirectededges elements, positions endvertices, opposite, origin, destination, isdirected, degree, indegree, outdegree incidentedges, inincidentedges, outincidentedges, adjacentvertices, inadjacentvertices, outadjacentvertices, areadjacent insertvertex, insertedge, insertdirectededge, removeedge, makeundirected, reversedirection, setdirectionfrom, setdirectionto removevertex suoritusaika O(1) O(1) O(n) O(m) O(n+m) O(1) O(m) O(1) O(m) 9. luku 472
Vierekkyyslistarakenne Graafin G vierekkyyslistarakenne laajentaa kaarilistaa lisäten tietoa, joka tukee solmuun liittyvien kaarien suoraa saantia. Kun kaarilista katsoo kaari solmu suhdetta ainoastaan kaarien näkökulmasta, vierekkyyslista katsoo sitä molempien komponenttien näkökulmasta. Tämä symmetrinen lähestymistapa mahdollistaa graafin abstraktin tietotyypin solmumetodien toteuttamisen paljon nopeammiksi kuin kaarilistan yhteydessä, vaikka näiden muistitilankäyttö on samaa luokkaa suhteessa solmujen ja kaarien määriin. Vierekkyyslista sisältää seuraavat piirteet: kaikki kaarilistan rakenneosat ja lisäksi Solmun v solmuolio käsittää viittauksen säiliöön I(v), joka sisältää solmuun v liittyvien kaarien oliot. Kaaren (u,v) kaariolio käsittää viittaukset kaaren paikkoihin säiliöissä I(u) ja I(v). 9. luku 473
Solmun v säiliö I(v) toteutetaan yleensä sekvenssinä, mutta myös mm. sanakirja tai prioriteettijono tulevat kysymykseen kontekstista riippuen. Kun vierekkyyslistaa vielä hieman muunnetaan, saadaan mukaan mahdollisuus, että voi olla sekä suuntaamattomia että suunnattuja kaaria. Käytetään kolmea säiliötä I in (v), I out (v) ja I un (v), jotka sisältävät viittaukset kaariolioihin ja nämä ovat suunnattuja tulevia, suunnattuja lähteviä tai suuntaamattomia kaaria solmuun v liittyen. Kuvassa 9.4. on edeltävän lentoreitistöesimerkin kuvaus vierekkyyslistana. Siinä on lisätty edeltävään verrattuna vierekkyysrakenteet jokaista graafin solmua varten. Mukana ei ole suuntaamattomien kaarien säiliöitä, koska suuntaamattomia kaaria ei ollut mukana esimerkissä. Vierekkyysrakenteiden avulla voidaan nopeuttaa useiden graafimetodien toimintaa. 9. luku 474
E: NW 35 DL 247 AA 49 DL 335 AA1387 AA 523 AA 411 UA 120 AA 903 UA 877 TW 45 V: BOS LAX DFW JFK MIA ORD SFO in out NW 35 DL 247 in AA 49 AA 411 out UA120 in AA1387 UA 877 AA 523 out DL 335 AA 49 in NW 35 out AA1387 AA 903 TW 45 in TW 45 out Kuva 9.4. Vierekkyyslistan kaavamainen esitys lentoreitistön tapauksesssa. in DL 247 AA 903 out AA523 AA 411 9. luku 475 in UA 120 DL 335 out UA 877
Taulukko 9.2. Graafimetodien suoritusajat, kun graafi on toteutettu vierekkyyslistana, jossa sekä säiliöt V ja E että vierekkyysrakennesäiliöt on toteutettu sekvensseinä ja nämä kahteen suuntaan linkitettyinä listoina. Tilavaatimus on O(n+m), missä n on solmujen lukumäärä ja m kaarien lukumäärä. operaatio suoritusaika size, isempty, replaceelement, swap numvertice, numedges vertices edges, directededges, undirectededges elements, positions endvertices, opposite, origin, destination, isdirected, degree, indegree, outdegree incidentedges(v), inincidentedges(v), outincidentedges(v), adjacentvertices(v), inadjacentvertices(v), outadjacentvertices(v) areadjacent(u,v) insertvertex, insertedge, insertdirectededge, removeedge, makeundirected, reversedirection, setdirectionfrom, setdirectionto removevertex(v) O(1) O(1) O(n) O(m) O(n+m) O(1) O(deg(v)) O(min(deg(u),deg(v))) O(1) O(deg(v)) 9. luku 476
Vierekkyysmatriisirakenne Kuten vierekkyyslista, myös graafin vierekkyysmatriisirakenne laajentaa kaarirakennetta lisäkomponentilla. Nyt lisätään kaarilistan lisäksi matriisi (taulukko) A, josta saadaan määrättyä solmuparien vierekkäisyysominaisuus vakioajassa. Muutamien metodien nopeutus aiheuttaa toisaalta aiempaa suuremman tilavaatimuksen. Tulkitaan solmut nyt kokonaislukuina joukosta {0, 1,, n 1} ja kaaret tällaisten kokonaislukujen pareina. Viittaukset kaariin voidaan nyt tallettaa kaksiulotteisen n n taulukon A alkioihin. Vierekkyysmatriisiesitys laajentaa kaarilistaa seuraavasti (kuva 9.5.): Solmun v olio tallettaa erillisen kokonaislukuavaimen väliltä 0, 1,, n 1. Se on solmun v indeksi (index). Käytetään kuitenkin yksinkertaisuuden vuoksi nimitystä solmu i indeksin sijasta. 9. luku 477
Taulukon alkio A[i,j] käsittää viittauksen kaariolioon e, joka menee solmusta i solmuun j. Mikäli tämä on suuntaamaton, e talletetaan sekä alkioon A[i,j] että A[j,i]. Kun kahden solmun välillä ei ole kaarta, jätetään vastavaat alkiot tyhjiksi. Vaikka jotkut metodit nyt ovat nopeampia kuin edeltävien rakenteiden yhteydessä, muutamien muiden suoritusaika kasvaa, koska esim. solmumetodien tilanteissa on käytävä läpi kokonainen rivi tai sarake taulukosta. Lisäksi muistitilavaatimus kasvaa kertaluokkaan O(n 2 ). Myös mikä tahansa solmun lisäys tai poisto vaatii nyt koko taulukon läpikäynnin, joka on O(n 2 ). 9. luku 478
0 1 2 3 4 5 6 BOS DFW JFK LAX MIA ORD SFO (a) 0 1 2 3 4 5 6 0 NW DL 35 247 1 AA DL 49 335 2 AA AA 1387 903 3 UA 120 4 AA AA 523 411 5 UA 877 6 (b) Kuva 9.5. Vierekkyysmatriisi: (a) graafin G solmujen indeksit ja (b) taulukko A. TW 45 9. luku 479
Taulukko 9.3. Graafimetodien suoritusajat, kun graafi on toteutettu vierekkyysmatriisina. Tilavaatimus on O(n 2 ), missä n on solmujen lukumäärä. Kaarien määrä on m. operaatio suoritusaika size, isempty, replaceelement, swap O(1) numvertice, numedges O(1) vertices O(n) edges, directededges, undirectededges O(m) elements, positions O(n+m) endvertices, opposite, origin, destination, O(1) isdirected, degree, indegree, outdegree incidentedges, inincidentedges, O(n) outincidentedges, adjacentvertices, inadjacentvertices, outadjacentvertices areadjacent O(1) insertedge, insertdirectededge, removeedge, O(1) makeundirected, reversedirection, setdirectionfrom, setdirectionto insertvertex, removevertex O(n 2 ) 9. luku 480
9.3. Graafin kulkeminen Kulkeminen (traversal) on järjestelmällinen tapa käydä graafi läpi tutkien kaikki solmut ja kaaret. Kulkeminen on tehokasta, kun se suoritetaan ajassa, joka on lineaarisessa suhteessa solmujen ja kaarien määrään. Tässä tarkastellaan suuntaamattomien graafien kulkemista. Syvyyshaku Ensimmäinen tarkasteltava menetelmä on syvyyshaku (depth first search), jota kuvan 9.6. tilanteet esittävät. Aloitetaan graafin määrätystä alkusolmusta s, joka kiinnitetään merkitsemällä se käydyksi. Solmu s on nyt nykyinen solmu u. Graafi käydään läpi ottamalla (mielivaltaisesti valittu) kaari (u,v). Jos tämä johtaa jo käytyyn solmuun v jossakin tilanteessa, palataan solmuun u. Jos toisaalta solmu v oli käymätön, mennään siihen ja merkitään se nykyiseksi ja käydyksi solmuksi. 9. luku 481
Edeltävää toimenpidettä toistetaan, kunnes tullaan umpikujaan eli solmuun, jonka kaikki viereiset solmut on aiemmin käyty. Tällöin peräännytään tultua reittiä takaisinpäin, kunnes löydetään sellainen käymätön kaari ja siis solmu, jolla on käymätön viereinen solmu. Tästä jatketaan taas eteenpäin käymättömiä solmuja edellisin ohjein. Prosessi loppuu, kun lopulta peräännytään alkusolmuun s. Syvyyshakua voidaan kuvata esittämällä kaaret sen mukaan, mihin suuntaan ne kuljetaan. Kaaret, joiden päästä saadaan uusi, ennenkäymätön solmu, ovat löytökaaria (discovery edges, tree edges), ja kaaret, joiden kautta tullaan aiemmin käytyihin, ovat perääntymiskaaria (back edges) (kuva 9.6.). Edellisten avulla saadaan haussa uusia solmuja ja jälkimmäisillä peräännytään. Löytökaarista saadaan tarvittaessa myös virittävä puu. Koodissa 9.1. on syvyyshakualgoritmin pseudokoodi. Siinä oletetaan olevan mukana mekanismi, jolla selvitetään, onko solmussa tai kaaressa käyty. 9. luku 482
A B C D A B C D E F G H E F G H I J K L I J K L M N O P M N O P (a) (b) Kuva 9.6. (alku) Esimerkki syvyyshausta. Löytökaaret on merkitty yhtenäisillä viivoilla ja perääntymiskaaret katkoviivoilla: (a) syötegraafi ja (b) löytökaarien polku aina solmuun A asti, kunnes kohdataan perääntymiskaari (B,A). 9. luku 483
A B C D A B C D E F G H E F G H I J K L I J K L M N O P M N O P (c) (d) Kuva 9.6. (jatkoa) (c) Solmun F saavuttaminen, joka on umpikuja, ja (d) Perääntymisen jälkeen solmuun C, josta on edetty kaaren (C,G) kautta jälleen umpikujaan, solmuun J. 9. luku 484
A B C D A B C D E F G H E F G H I J K L I J K L M N O P M N O P (e) (f) Kuva 9.6. (loppu) (e) Perääntymisen jälkeen solmuun G ja (f) perääntymisen jälkeen solmuun N. 9. luku 485
Algorithm DFS(v): Input: solmu v graafista Output: kaaret merkittyinä löytö ja perääntymiskaarina for jokaiselle solmuun v liittyvälle kaarelle e do if kaari e on käymätön then olkoon w kaaren e toinen päätesolmu if solmu w on käymätön then merkitse e löytökaareksi kutsu rekursiivisesti algoritmia DFS(w) else merkitse e perääntymiskaareksi Koodi 9.1. Syvyyshakualgoritmi. 9. luku 486
Syvyyshakuun liittyy monia seikkoja, joista mainitaan esimerkkinä se, että kun perääntymiskaaret yhdistävät aina solmun v aiemmin käytyyn solmuun u, ne muodostavat syklin graafissa. Seuraava lause esittää muutamia ominaisuuksia. Lause 9.5. Olkoon G suuntaamaton graafi, jossa syvyyshaku aloitetaan solmusta s. Silloin ovat ominaisuudet: Kuljettaessa graafi käydään kaikki solmut läpi solmun s yhdistetyssä komponentissa. Löytökaaret muodostavat s:n yhdistetyn komponentin virittävän puun. Perustelu jätetään väliin, mutta se on esitettävissä vastaväitetodistusta käyttäen. yksinkertaista Syvyyshaku on suoritusajaltaan tehokas, kun solmussa tehtävät toimenpiteet (testi ja merkintä) ovat suoritettavissa vakioajassa O(1). 9. luku 487
Algoritmia kutsutaan täsmälleen kerran jokaista solmua kohti, ja jokainen kaari tutkitaan kahdesti, kerran sen kummastakin päätesolmusta käsin. Muutamin edellytyksin solmun testin ja merkinnän vakioaika, solmu ja kaarimetodien vakiollinen suoritusaika (vierekkyyslista, mutta ei matriisi) ja systemaattinen menettely käydä solmuun liittyvät kaaret ainoastaan kerran kussakin (vierekkyyslista) saadaan syvyyshaulle tehokas suoritus aikaan. Lause 9.6. Olkoon G graafi n solmuineen ja m kaarineen. Syvyyshaku toimii siinä ajassa O(n+m). Lisäksi on olemassa syvyyshakuun perustuvia algoritmeja, jotka toimivat ajassa O(n+m) ongelmille: Sen tutkiminen, onko G yhdistetty. Virittävän puun laskeminen, kunhan G on yhdistetty. G:n yhdistettyjen komponenttien laskeminen. Kahden solmun välisen polun etsiminen tai selvittäminen, ettei sitä ole. Mahdollisen syklin laskeminen. 9. luku 488
Leveyshaku Syvyyshaun tapaan leveyshaku (breadth first search) kulkee graafin yhdistetyn komponentin täysin läpi. Leveyshaku etenee konservatiivisesti tasoittain graafia (kuva 9.7.), kun taas sysyyshaussa sukellettiin syvyyksiin. Olkoon aloitussolmu s tasona 0. Se on aluksi kiintopisteenä, josta käydään seuraava taso 1 läpi eli solmun s vierekkäiset solmut. Solmuun tultaessa se merkitään käydyksi. Seuraavaksi käydään tason 1 solmujen vierekkäiset solmut läpi, ja tämä on taso 2. Näin jatketaan tasolta i tasolle i+1, kunnes kaikki solmut ja kaaret on käyty läpi. Leveyshaun kauniina piirteenä on, että jokainen solmu käydään läpi ja merkitään (nimetään, leimataan) lyhimmän polun mielessä eli minimimäärällä kaaria aloitussolmusta lukien. Jos solmu v sijaitsee leveyshaun tasolla i, sen lyhimmän polun pituus solmusta s on i. 9. luku 489
0 0 1 A B C D A B C D E F G H E F G H I J K L I J K L M N O P M N O P (a) (b) Kuva 9.7. (alku) Esimerkki leveyshausta, jossa solmuihin liittyvät kaaret tutkitaan aakkosjärjestyksessä vierekkäisistä solmuista. Löytökaaret on merkitty yhtenäisillä nuolilla ja vastakkaiskaaret (ei vielä tässä) katkoviivoilla. (a) Graafi aloitusvaiheessa ja (b) tason 1 käsittely. 9. luku 490
0 1 2 0 1 2 3 A B C D A B C D E F G H E F G H I J K L I J K L M N O P M N O P (c) (d) Kuva 9.7. (jatkoa) (c) Tason 2 käsittely ja (d) tason 3 käsittely. 9. luku 491
9. luku 492 A E I B C D N F J G H O K L P M (e) 0 1 2 3 4 A E I B C D N F J G H O K L P M (f) 0 1 2 3 4 5 Kuva 9.7. (loppu) (e) Tason 4 ja (f) tason 5 käsittelyt. E F B
Syvyyshaun tapaan leveyshaussa merkitään kaaret kahdella tyypillä. Uusiin solmuihin johtavat ovat jälleen löytökaaria, mutta aiemmin käytyihin johtavat ovat vastakkaiskaaria (cross edges) (kuva 9.7.(f)) erotuksena syvyyshakuun, sillä nämä eivät yhdistä solmua edeltäjiinsä. Leveyshaun pseudokoodiesitys on koodina 9.2. Se tarvitsee lisätilaa kaarien ja solmujen merkitsemiseen ja tasoihin liitettävien säiliöiden tallettamiseen. Algoritmi ei ole rekursiivinen. Leveyshaulla on monia ominaisuuksia, joita selostetaan seuraavasti. Lause 9.7. Olkoon G suuntaamaton graafi, jossa leveyshaku aloitetaan solmusta s. Silloin ovat ominaisuudet: Graafissa käydään läpi kaikki solmut s:n yhdistetyssä komponentissa. Löytökaaret muodostavat s:n yhdistetyn komponentin virittävän puun T, jota kutsutaan leveyshakupuuksi. Leveyshakupuun T polku solmusta s solmuun v tasolle i käsittää i kaarta ja mikä tahansa muu polku niiden välillä on ainakin yhtä pitkä. Jos (u,v) ei ole T:ssä, u:n ja v:n tasonumerot eroavat enintään yhdellä. 9. luku 493
Algorithm BFS(s): alustetaan säiliö L 0 sisältämään solmu s i 0 while L i ei ole tyhjä do luodaan tyhjä säiliö L i+1 for jokaiselle solmulle v säiliöstä L i do for jokaiselle solmuun v liittyvälle kaarelle e do if kaari e on käymätön then olkoon w kaaren e toinen päätesolmu if solmu w on käymätön then merkitään e löytökaareksi lisätään w säiliöön L i+1 else i i + 1 merkitään e vastakkaiskaareksi Koodi 9.2. Leveyshakualgoritmi. 9. luku 494
Lause 9.8. Olkoon G graafi n solmuineen ja m kaarineen. Leveyshaku graafissa G vaatii ajan O(m+n). On myös muita samassa ajassa toimivia, leveyshakuun perustuvia algoritmeja: Sen tutkiminen, onko G yhdistetty. G:n virittävän puun laskeminen, kunhan G on yhdistetty. G:n yhdistettyjen komponenttien laskeminen. G:n mille tahansa solmulle v lyhimmän polun laskeminen aloitussolmusta s. Kumpaa tulisi käyttää näistä menetelmistä, riippuu sovelluksesta. Esim. lyhimmän polun laskennassa leveyshaku on syvyyshakua parempi. Syvyyshaku on puolestaan soveliaampi vastattaessa monimutkaisiin yhteyskysymyksiin, kuten voidaanko jokainen graafin solmupari yhdistää kahdella erillisellä polulla. Nämä tulokset pätevät kuitenkin vain suuntaamattomille graafeille, joten seuraavaksi tarkastellaan suunnattuja. 9. luku 495
9.4. Suunnatut graafit Graafi on suunnattu, jos sen kaaret ovat suunnattuja. Saavutettavuus Saavutettavuuden (reachability) tärkeässä käsitteessä on kysymys siitä, mihin suunnatussa graafissa G päästään kulkemaan. Kulkeminen graafissa tapahtuu luonnollisesti kaarien määrätyissä suunnissa, mikä vaikuttaa itse prosessiin. Solmuilla u ja v sanotaan u:n saavuttavan v:n (ja v on saavutettavissa u:sta), jos on olemassa suunnattu polku u:sta v:hen. Suunnattu graafi G on vahvasti yhdistetty (strongly connected), jos mille tahansa sen solmuparille u ja v edellinen saavuttaa jälkimmäisen ja päinvastoin. G:n suunnattu sykli (directed cycle) on sellainen, jossa kaikki sen kaaret käydään suuntiensa mukaan läpi. G on syklitön (acyclic), jos siinä ei ole yhtään suunnattua sykliä (kuva 9.8.). 9. luku 496
BOS ORD JFK SFO DFW LAX MIA (a) Kuva 9.8. (alku) Esimerkkejä saavutettavuudesta suunnatussa graafissa: (a) suunnattu polku lentokentältä BOS kentälle LAX. 9. luku 497
BOS ORD JFK SFO DFW LAX MIA (b) Kuva 9.8. (jatkoa) (b) Suunnattu sykli (ORD, MIA, DFW, LAX, ORD). 9. luku 498
BOS ORD JFK SFO DFW LAX MIA (c) Kuva 9.8. (jatkoa) (c) Solmusta ORD saavutettavien solmujen ja kaarien aligraafi käsittää muut paitsi solmut JFK ja BOS. 9. luku 499
BOS ORD JFK SFO DFW LAX MIA (d) Kuva 9.8. (loppu) (d) Katkoviivoilla merkityt kaaret poistamalla saadaan syklitön suunnattu graafi. 9. luku 500
Suunnatun graafin G transitiivinen sulkeuma (transitive closure) G* käsittää G:n solmut ja kaaret (u,v), joille on olemassa suunnattu polku solmusta u solmuun v graafissa G. G* määritellään siis niin, että otetaan G ja lisätään sellaiset kaaret (u,v), joissa v on saavutettavissa solmusta u (eikä G: ssä ollut jo kyseisiä kaaria). Saavutettavuutta koskevia mielenkiintoisia kysymyksiä ovat suunnatun graafin tapauksessa seuraavat: Onko solmu v saavutettavissa solmusta u? Kaikkien sellaisten solmujen etsiminen, jotka ovat saavutettavissa solmusta s käsin. Onko G vahvasti yhdistetty? Onko G syklitön? G:n transitiivisen sulkeuman laskeminen. 9. luku 501
Suunnatun graafin kulkeminen Kuten suuntaamattomilla graafeilla, suunnatuillakin käytetään samankaltaisia kulkemisalgoritmeja. Ainoa ero on, että nyt on otettava huomioon kaarien suunnat. Seuraavaksi esitetään rekursiivinen suunnattu syvyyshakualgoritmi koodina 9.3. Sen käytöstä on esimerkki kuvassa 9.9. Algorithm DirectedDFS(v): merkitään solmu v käydyksi for jokaiselle solmun v lähtevälle kaarelle (v,w) do if solmussa w ei ole käyty then kutsu rekursiivisesti algoritmia DirectedDFS(w) Koodi 9.3. Suunnatun syvyyshaun algoritmi. 9. luku 502
BOS ORD JFK SFO DFW LAX MIA (a) Kuva 9.9. (alku) Esimerkki suunnatun graafin syvyyshausta: (a) välivaihe, jossa saavutetaan ensi kertaa aiemmin käyty solmu (DFW). 9. luku 503
1 BOS 7 SFO ORD 5 JFK 2 DFW 3 LAX 4 (b) MIA 6 Kuva 9.9.(loppu) (b) Päättynyt suunnatun graafin syvyyshaku, jossa on solmujen käyntijärjestys merkitty numeroin. 9. luku 504
Suunnatun graafin syvyyshakualgoritmi toimii suuntaamattoman tapaan ajassa O(n+m), missä n on solmujen ja m kaarien määrä. Muutamat suunnattuihin graafeihin liittyvät ongelmat, kuten sen selvittäminen, onko graafi vahvasti yhdistetty, tai transitiivisen sulkeuman laskeminen, vaativat ajan O(n(n+m)). Suunnatut syklittömät graafit Suunnattuja syklittömiä graafeja (directed acyclic graph, DAG) tarvitaan monissa sovelluksissa. Esimerkkinä on Java kielisen ohjelman luokkien välinen periytyminen. Olkoon G suunnattu syklitön graafi, jossa on n solmua. Sen topologinen järjestys (topological ordering) on solmujen järjestys v 1,, v n, missä jokaiselle kaarelle (v i,v j ) on i<j. Topologinen järjestys merkitsee, että mikä tahansa G:n suunnattu polku käy solmut läpi kasvavassa järjestyksessä. Kuvassa 9.10. on kaksi esimerkkiä näistä. Topologinen järjestys lasketaan topologisen lajittelun (topological sorting) algoritmilla, mutta sitä ei esitetä tässä. 9. luku 505
9. luku 506 A B C D F E G I H 1 3 2 4 5 6 7 8 9 (a) A B C D F E G I H 1 2 4 5 6 3 8 7 9 (b) Kuva 9.10. Kaksi topologista järjestystä samasta suunnatusta syklittömästä graafista. Järjestysnumero on merkitty solmun viereen.