Tietorakenteet, kevät 2012 Kurssikoe 2, mallivastaukset 2. (a) Järjestämistä ei voi missään tilanteessa suorittaa nopeammin kuin ajassa Θ(n log n), missä n on järjestettävän taulukon pituus. Epätosi: Yleisessä tapauksessa, jos alkioista ei tiedetä mitään, väite pitää paikkansa, sillä alkioita joudutaan vertailemaan, mutta esim. rajoitetulle kokonaislukujoukolle laskemisjärjestäminen on lineaariaikainen. (b) Jos verkko on täydellinen, eli kaikkien solmuparien välillä on olemassa kaari, niin syvyyssuuntainen läpikäynti vie aikaa Θ(n 2 ), missä n on verkon solmujen lukumäärä. Tosi: Algoritmin aikavaativuus on O( V + E ). Koska täydellisessä verkossa on jokaista solmua kohden n kappaletta DFS-visitin for-loopissa tarkastettavia kaaria, aikavaativuus on toisin sanoen Θ(n 2 ). Useassa vastauksessa oli pidetty väittämää epätotena vedoten siihen, että aikavaativuus on O( V + E ). Tarkoituksena on kuitenkin osoittaa, että täydelliselle suunnatulle verkolle nimenomaan O( V + E ) = Θ(n + (n-1)*(n) / 2) = Θ(n 2 ), sillä täydellisessä suunnatussa verkossa kaarten lukumäärä on (n-1)*(n) kaarta (ja suuntaamattomassa tietysti (n-1)*(n) / 2). Tämä on selvää, jos ajatellaan, että ensimmäisestä solmusta vedetään kaaret n-1 solmuun, toisesta n-2, ja niin edelleen, kunnes toiseksi viimeisestä vedetään yksi solmu viimeiseen. Summakaavalla saadaan yllä oleva lauseke. Oikeasta tosi-epätosi -väittämästä saa pisteen, ja hyvästä perustelusta toisen.
4. Tehtävässä tulee löytää lyhin mahdollinen polku solmusta s solmuun t, joten leveyshaku on järkevin ratkaisu, sillä ensimmäinen löytyvä polku on myös lyhin (tai yksi lyhimmistä). Siniset ja punaiset kaaret tulee ottaa huomioon siten, että jokainen solmu muistaa, minkä väristä kaarta pitkin siihen on tultu, eikä jatka leveyshakua samanvärisiä kaaria pitkin. Käytetään apujonoa Q, apupinoa S, ja kummallekin värille aputauluja visited, distance ja tree (tai tallennetaan nämä tiedot solmuihin). Kumpikin väri tarvitsee oman aputaulukon, sillä tilanne, jossa samaan solmuun johtaa kaksi eripituista eriväriseen kaareen päättyvää solmua johtaa vaikeuksiin (ks. viimeinen sivu). Kun solmuun on kerran saavuttu (visited) sekä punaisesta, että sinisestä solmusta, sitä ei tarvitse enää käsitellä. RedBlue-BFS(G,s,t) for jokaiselle u ϵ V red-visited = false blue-visited = false red-distance[u] = blue-distance[u] = red-tree[u] = NIL blue-tree[u] = NIL red-distance[s] = 0 blue-distance[s] = 0 red-visited[s] = true blue-visited[s] = true enqueue(q,s) while(not empty(q)) u = dequeue(q) for jokaiselle v ϵ vierus[u] if red-visited[v] and blue-visited[v] continue if edgecolor(u,v) == blue and red-distance[u] < blue-distance[v] blue-distance[v] = red-distance[u] + 1 blue-tree[v] = u blue-visited[v] = true if edgecolor(u,v) == red and blue-distance[u] < red-distance[v] red-distance[v] = blue-distance[u] + 1 red-tree[v] = u red-visited[v] = true if v == t return min(red-distance[t], blue-distance[t]) return
u = blue-tree[t] nextcolor = red if red-distance[t] < blue-distance[t] u = red-tree[t] nextcolor = blue while u!= s push(s,u) if nextcolor == red u = red-tree[u] nextcolor = blue else u = blue-tree[u] nextcolor = red while (not empty(s)) u = pop(s) print(u) Toinen toimiva vaihtoehto on tehdä kaksi verkkoa G ja G', joissa on samat solmut, mutta siniset kaaret alkavat verkosta G ja saapuvat G':n solmuihin, ja punaiset kaaret alkavat verkosta G' ja päättyvät G:n solmuihin. Nyt suoritetaan leveyshaku siten, että aloitetaan kummankin verkon s- solmusta ja päädytään kumman tahansa verkon t-solmuun. Yksi ratkaisu on myös voi lähteä etenemään molemmista suunnista, sillä jompi kumpi reitti pääsee aina etenemään. Arvostelu: 8p Toimiva ratkaisu, jossa aikavaativuus oikein. 7p Ratkaisu ei ihan toimi, joitain loogisia virheitä tai puutteita. 6p Ratkaisu hyvä, mutta on myös virheitä. Maksimipistemäärä pelkällä seuraavalla sivulla kuvatulla leveyshaulla. 4-5p Oikean suuntaisia ideoita toteutettuna, mutta on myös oleellisia puutteita. Seuraavan sivun leveyshakuversio oikein vähäisillä puutteilla. 1-3p Ratkaisussa oikeita elementtejä, mutta siinä on myös merkittäviä puutteita, se on kesken, sekava, tai aikavaativuutta ei saavuteta. 0p Ei yritystä tai yritys on mitätön. -1p / -2p Tulostus on virheellinen tai puuttuu.
4. HIEMAN VIRHEELLINEN VERSIO Varsin moni vastasi seuraavan kaltaisella algoritmilla, joka ei kuitenkaan toimi yleisessä tapauksessa, jos solmuun tulee sekä sininen, että punainen kaari, ja vain pidempää reittiä pääsee maaliin. Leveyshaku on hyvä idea, mutta pitää olla tarkkana, ettei estä hakua ennen kuin sekä punainen, että sininen tulokaari on käsitelty. Muutamassa vastauksessa oli tarkasteltu erikseen punaisella ja sinisellä kaarella alkavat reitit. Tämä on yksi toimiva tapa pitää kirjaa siitä, että joka toinen kaari on punainen ja joka toinen sininen, mutta sekään ei auta yllä mainittuun ongelmaan jos haarautuva kohta on aloitussolmun naapureita kauempana verkossa (ks. viimeisen sivun kuva). Käytetään apujonoa Q, apupinoa S, ja aputauluja color, distance ja tree (tai tallennetaan nämä tiedot solmuihin). Solmun väri color on aluksi white, ja myöhemmin red tai blue tulokaaren värin mukaan. RedBlue-BFS(G,s,t) for jokaiselle u ϵ V color[u] = white distance[u] = tree[u] = NIL distance[s] = 0 color[s] = black enqueue(q,s) while(not empty(q)) u = dequeue(q) for jokaiselle v ϵ vierus[u] if edgecolor(u,v)!= color(u) and color[v] == white color[v] = edgecolor(u,v) distance[v] = distance[u] + 1 tree[v] = u if v == t u = tree[v] while u!= s push(s,u) u = tree[u] while (not empty(s)) u = pop(s) print(u)
Ei toimi esim. seuraavalla verkolla, koska s:n ja t:n välinen solmu ei ole enää valkoinen, kun siihen päästään: