IN Algoritmer og datastrukturer GRAER IN Algoritmer og datastrukturer Dagens plan: orteste vei, en-til-alle, for: ektet rettet graf uten negative kanter (apittel 9..) (Dijkstras algoritme) ektet rettet graf med negative kanter (apittel 9..) Minimale spenntrær Prim (apittel 9..) ruskal (apittel 9..) orteste vei i en vektet graf uten negative kanter Graf uten vekter: elger først alle nodene med avstand fra startnoden, så alle med avstand osv Mer generelt: elger hele tiden en ukjent node blant dem med minst avstand fra startnoden Den samme hovedidéen kan brukes hvis vi har en graf med vekter Akkurat som for uvektede grafer, ser vi bare etter potensielle forbedringer for naboer som ennå ikke er valgt (kjent) Dybde først søk (apittel 9..) inne sammenhengskomponenter Løkkeleting Ark av Denne algoritmen ble publisert av Dijkstra i 99 og har fått navn etter ham orelesning.. orelesning.. Ark av IN Algoritmer og datastrukturer Dijkstras algoritme. or alle noder: Sett avstanden fra startnoden s lik Merk noden som «ukjent». Sett avstanden fra s til seg selv lik. elg en ukjent node v med minimal avstand fra s (det kan være flere med samme avstand), og marker v som «kjent». or hver ukjent nabonode w til v: Dersom avstanden vi får ved å følge veien gjennom v, er kortere enn den gamle avstanden til s reduserer avstanden til s for w sett bakoverpekeren i w til v. Så lenge det finnes ukjente noder, gå til punkt Merk: Dijkstras algoritme virker både på rettede og urettede grafer IN Algoritmer og datastrukturer Hvorfor virker algoritmen? Algoritmen har følgende invariant: Ingen kjent node har større avstand til s enn en ukjent node ølgelig har alle kjente noder riktig korteste vei satt (registrert avstand er lavest mulig kost av en vei til s) i plukker ut en ukjent node v med minst avstand (d v ), markerer den som kjent og påstår at avstanden til v er riktig Denne påstanden holder fordi d v er den korteste veien som finnes ved å bruke bare kjente noder de kjente nodene har riktig korteste vei satt en vei til v som er kortere enn d v, må nødvendigvis forlate mengden av kjente noder et sted, men d v er allerede den korteste veien fra kjente noder til v Dette argumentet holder fordi vi ikke har negative kanter orelesning.. Ark av orelesning.. Ark av
IN Algoritmer og datastrukturer Eksempel Den første noden som velges, er startnoden IN Algoritmer og datastrukturer 9 Naboene til har fått endret sin avstand og fått tilbakepekere til Nå er nærmeste ukjente node har fått endret sin avstand og fått tilbakepeker til Nå er nærmeste ukjente node Merk at den aldri senere kan få endret sin avstand 9 9 har fått ny avstand og tilbakepeker, mens er nærmeste ukjente node orelesning.. Ark av har fått ny avstand og tilbakepeker, og og er nærmeste ukjente noder orelesning.. Ark av IN Algoritmer og datastrukturer IN Algoritmer og datastrukturer i velger som blir kjent 9 9 Oppgave Bruk Dijkstras algoritme, og fyll ut tabellen nedenfor! Nå er nærmest og blir kjent Initielt: v v kjent avstand vei v v kjent avstand vei v v 9 9 v v v v får ny avstand og tilbakepeker i kan nå avslutte med å gjøre kjent v v v v v v orelesning.. Ark av orelesning.. Ark av
idsforbruk IN Algoritmer og datastrukturer Hvis vi leter sekvensielt etter den ukjente noden med minst avstand tar dette O( ) tid, noe som gjøres ganger, så total tid for å finne minste avstand blir O( ) I tillegg oppdateres avstandene, maksimalt en oppdatering per kant, dvs. til sammen O( E ) otal tid: O( E + ) = O( ) Raskere implementasjon (for tynne grafer): Bruker en prioritetskø til å ta vare på ukjente noder med avstand mindre enn i må ta hensyn til at prioriteten til en ukjent node forandres hvis vi finner en kortere vei til noden DeleteMin og Decreaseey tar O(log ) tid otalt tidsforbruk blir O( log + E log ) = O( E log ) orelesning.. Ark 9 av IN Algoritmer og datastrukturer Hva med negative kanter? Dijkstras algoritme fungerer ikke hvis grafen har negative kanter (se oppgave 9.a) En mulig løsning: Nodene er ikke lenger «kjente» eller «ukjente» i har i stedet en kø som inneholder noder som har fått forbedret avstandsverdien sin Løkken i algoritmen gjør følgende: a ut en node v fra køen or hver etterfølger w, sjekk om vi får en forbedring Oppdater i så fall avstanden, og plasser w (tilbake) i køen (hvis den ikke er der allerede) idsforbruket blir O( E ) som er mye verre enn Dijkstras algoritme Det finnes ingen korteste vei hvis det er negative løkker i G, og det er det hvis og bare hvis samme node blir tatt ut av køen mer enn ganger Da må vi terminere algoritmen orelesning.. Ark av IN Algoritmer og datastrukturer Minimale spenntrær Et minimalt spenntre for en urettet graf G er et tre bestående av kanter fra grafen, slik at alle nodene i G er forbundet til lavest mulig kostnad Minimale spenntrær eksisterer bare for sammenhengende grafer Generelt kan det finnes flere minimale spenntrær for samme graf IN Algoritmer og datastrukturer Grådige algoritmer Prøver i hvert trinn å gjøre det som ser best ut der og da ypisk eksempel: Gi vekslepenger Raske algoritmer, men kan ikke løse alle problemer: inn det høyeste punktet! i skal se på to ulike grådige algoritmer for å finne minimale spenntrær??? Hvor mange kanter får spenntreet i det generelle tilfellet? orelesning.. Ark av orelesning.. Ark av
IN Algoritmer og datastrukturer Prims algoritme reet bygges opp trinnvis I hvert trinn legges en kant (og dermed en tilhørende node) til treet i har til enhver tid to typer noder: Noder som er med i treet Noder som ikke er med i treet Nye noder legges til ved å velge en kant (u, v) med minst vekt slik at u er med i treet, og v ikke er det. IN Algoritmer og datastrukturer Minste kant ut fra v går til v, så vi legger den inn i spenntreet Algoritmen begynner med å velge en vilkårlig node Eksempel: La oss velge v orelesning.. Ark av orelesning.. Ark av IN Algoritmer og datastrukturer IN Algoritmer og datastrukturer i har nå to mulige fortsettelser: anten fra v til v anten fra v til v Samme hvilken vi velger, vil den andre av dem bli neste kant, så vi legger dem begge inn i spenntreet Minste kant ut fra spenntreet går nå fra v til v Så får vi kanten fra v til v Endelig får vi kanten fra v til v Det ferdige spenntreet blir: orelesning.. Ark av orelesning.. Ark av
IN Algoritmer og datastrukturer Prims algoritme er essensielt lik Dijkstras algoritme for å finne korteste vei! I Prims algoritme er «avstanden» til en ukjent node v den minste vekten til en kant som forbinder v med en kjent node Husk at vi har urettede grafer, slik at hver kant befinner seg i to nabolister jøretidsanalysen er den samme som for Dijkstras algoritme IN Algoritmer og datastrukturer a v s t. f r a I n i t i a l t i l s t a n d e n a v s t. f r a a v s t. f r a a v s t. f r a v v v v v kjent avstand vei v v v orelesning.. Ark av orelesning.. Ark av IN Algoritmer og datastrukturer IN Algoritmer og datastrukturer Hvorfor virker Prim? Løkke-lemmaet: Anta at er et spenntre for en graf, og at kanten e ikke er med i treet Om vi legger kanten e til treet, vil det dannes en entydig bestemt enkel løkke Hvis, og bare hvis, vi fjerner en vilkårlig kant i denne løkken, vil vi igjen ha et spenntre for grafen a v s t. f r a a v s t. f r a 9 -delen av lokka. f e a v s t. f r a a v s t. f r a. e r d i g! orelesning.. Ark 9 av : -: Prim-invarianten: Det treet som dannes av de kantene (og deres endenoder) vi til nå har plukket ut, er slik at det finnes et minimalt spenntre for grafen som inneholder (alle kantene i) orelesning.. Ark av
IN Algoritmer og datastrukturer IN Algoritmer og datastrukturer ruskals algoritme: Se på kantene en etter en, sortert etter minst vekt anten aksepteres hvis, og bare hvis, den ikke fører til noen løkke Algoritmen implementeres ved bruk av en prioritetskø og disjunkte mengder: Initielt legges kantene i en prioritetskø og nodene som hver sin disjunkte mengde Invariant: De disjunkte mengdene er subtrær av det endelige spenn-treet deletemin gir neste kant (u, v) som skal testes Hvis find(u)! = find(v), har vi en ny kant i treet og gjør union(u, v) Hvis ikke, ville (u, v) ha dannet en løkke, så kanten forkastes Algoritmen terminerer når prioritetskøen er tom, eventuelt når vi har lagt inn kanter Eksempel tgangspunkt for ruskals algoritme: i har to kanter med vekt De blir til to subtrær i spenn-treet orelesning.. Ark av orelesning.. Ark av IN Algoritmer og datastrukturer i har to kanter med vekt De blir del av det øverste subtreet i har en kant med vekt Den vil lage en løkke og må forkastes i har to kanter med vekt hvor den mellom v og v danner en løkke, mens den andre binder de to subtrærne sammen IN Algoritmer og datastrukturer i har en kant med vekt som lager løkke i har en kant med vekt Den knytter den siste noden til treet Nå har vi lagt inn kanter i spenn-treet og kan slutte Hvis vi fortsetter med resten av kantene, vil alle danne løkker og bli forkastet orelesning.. Ark av orelesning.. Ark av
idsanalyse: IN Algoritmer og datastrukturer Hovedløkken går E ganger I hver iterasjon gjøres en deletemin, to find og en union, med samlet tidsforbruk O(log E ) + O(log )+O() = O(log ) (fordi log E < log ) otalt tidsforbruk er O( E log ) Prim vs. ruskal Prims algoritme er noe mer effektiv enn ruskals, spesielt for tette grafer Prims algoritme virker bare i sammenhengende grafer ruskas algoritme gir et minimalt spenn-tre i hver sammenhengskomponent i grafen IN Algoritmer og datastrukturer Dybde-først søk Generalisering av prefiks traversering for trær. i starter i en node v og traverserer alle nabonodene rekursivt Rekursjonen gjør at vi undersøker alle noder som kan nåes fra første etterfølger til v, før vi undersøker neste etterfølger til v or en vilkårlig graf må vi passe på å unngå løkker: Markerer nodene som besøkt etterhvert som de behandles, og kaller rekursivt videre bare for umerkede noder void dybdeørstsøk(node v) { v.merke = true; for < hver nabo w til v > { if (!w.merke) { dybdeørstsøk(w); orelesning.. Ark av orelesning.. Ark av IN Algoritmer og datastrukturer Midtveis i en dybde-først traversering kan kjeden av rekursive metodekall og besøkt-merkene i nodene se slik ut: a* void DS(f) { DS (g) void DS(d) { DS (f) void DS(b) { DS (d) void DS(a) { DS (b) c b* Her er vi nå! g d* f * e * Noder merket * er besøkte Node e er allerede behandlet ferdig Nå behandles node f Den kommer til å kalle DS(g) DS(g) har ingen ikke besøkte etterfølgere Dermed må algoritmen «trekke seg tilbake» ørst i DS(b) finnes det en ikke besøkt etterfølger IN Algoritmer og datastrukturer Er grafen sammenhengende? Hvis grafen ikke er sammenhengende, kan vi foreta nye dybde-først søk fra noder som ikke er besøkte, inntil alle nodene er behandlet En urettet graf er sammenhengende hvis og bare hvis et dybde-først søk som starter i en tilfeldig node, besøker alle nodene i grafen En rettet graf er sterkt sammenhengende hvis og bare hvis vi fra hver eneste node v klarer å besøke alle de andre nodene i grafen ved et dybde-først søk fra v DS (a) orelesning.. Ark av orelesning.. Ark av
IN Algoritmer og datastrukturer IN Algoritmer og datastrukturer Løkkeleting i kan bruke dybde-først søk til å sjekke om en graf har løkker i trenger da tre verdier til tilstandsvariablen: usett, igang og ferdig (besøkt) void løkkelet(node v) { if (v.tilstand == igang) { < Løkke er funnet > else if (v.tilstand == usett) { v.tilstand = igang; for < hver nabo w til v > { løkkelet(w); v.tilstand = ferdig; Metoden bygger på at de nodene der kall er i gang, alltid ligger på en rett vei fra startnoden i må passe på å gjøre nye startkall inntil metoden er kalt i alle nodene Metoden for løkkeleting kan også gi oss en topologisk sortering (med nodene skrevet ut i omvendt rekkefølge) dersom grafen ikke har løkker Det får vi til ved å skrive ut noden like før vi trekker oss tilbake (idet vi er ferdig med kallet) Dette er riktig tidspunkt å skrive ut noden fordi: i har sjekket alle etterfølgerne til noden Disse var enten usette (og da har vi skrevet dem ut i det vi trakk oss tilbake fra dem), eller ferdige (og da var de skrevet ut tidligere) Dersom vi fant en node som var igang, har vi funnet en løkke... Metoden vil alltid finne en løkke dersom det eksisterer en! orelesning.. Ark 9 av orelesning.. Ark av