Grunnleggende Grafalgoritmer II Lars Vidar Magnusson March 17, 2015 Kapittel 22 Dybde-først søk Topologisk sortering Relasjonen til backtracking
Dybde-Først Søk Dybde-først søk i motsetning til et bredde-først søk vil gå så dypt som mulig før den returnerer. Input er en graf G = (V, E) som kan være enten rettet eller urettet. Output er to tidsstempler v.d og v.f som angir henholdsvis når en node oppdages og når den er ferdig utforsket. Tidsstemplene vil være til nytte for algoritmer vi skal se på senere. Koden i boka bygger også et dybde-først tre ved å lagre v.π. Algoritmen vi presenterer her garanterer å besøke alle noder i.e. den bygger en skog av dybde-først trær. Dette er ikke et krav.
Ideen bak Dybde-Først Søk I et dybde-først søk så begynner vi å undersøke en node så snart den oppdages Vi bruker ingen kø som i et bredde-først søk Dybde-først søket benytter seg av fargekoder under kjøringen av algoritmen white - hittils uoppdagede noder gray - oppdagede men ikke ferdig utforsket black - ferdig utforskede noder Tidstempelene følger følgende regler. Unike heltall mellom 1 og 2 V. v V : 1 v.d < v.f 2 V
Pseudokode for Dybde-Først Søk (DFS) Pseudokoden for dybde-først søk (DFS) er listet under. Koden bruker en global variabel time for å holde styr på tiden. Denne koden initialiserer algoritmen og sørger for at alle node blir besøkt. DFS kaller algoritmen DFS-Visit for å utføre selve søket.
Pseudokode for Dybde-Først Søk (DFS-Visit) Pseudokode for DFS-Visit er listet under. Denne algoritmen er ansvarlig for å utføre dybde-først søket.
Hvordan DFS Fungerer Figuren under viser hvordan DFS kjører på en eksempelgraf.
Analyse av DFS I et dybde-først søk vil alle noden utforskes én gang. Alle kanter besøkes én gang Dette gir oss en kjøretid på Θ(V + E). Dette er nesten det samme som BFS. Forskjellen mellom de to er at DFS besøker alle nodene og undersøker alle kantene i.e. Θ ikke O
Egenskaper ved DFS For alle u og v så gjelder en av de følgende forholdene. u.d < u.f < v.d < v.f eller v.d < v.f < u.d < u.f. Intervallene [u.d, u.f ] og [v.d, v.f ] er ikke overlappende i.e hverken u eller v er etterkommer av den andre. u.d < v.d < v.f < u.f. v er etterkommer av u. v.d < u.d < u.f < v.f. u er etterkommer av v. Det vil aldri skje at u.d < v.d < u.f < v.f. Dette er analogt med at d og f for de ulike nodene danner balanserte paranteser. v er en etterkommer av u bare hvis ved tiden u.d eksisterer en sti fra u til v med bare hvite noder (unntatt u).
Visulisering av Egenskapene ved DFS Figuren under viser hvordan egenskapene ved DFS henger sammen.
Klassifisering av Kanter Egenskapene til et dybde-først søk kan brukes til å klassifisere kantene i en graf. Tre-kant (tree): en kant som er med i dybde-først treet. Tilbake-kant (back): en kant fra en etterkommer til en forgjenger Forover-kant (forward): en kant fra en forgjenger til en etterkommer som ikke er med i dybde-først treet. Kryss-kant (cross): er alle andre kanter. I en urettet graf kan disse skillene by på noen problemer siden en kant går begge veier. I disse tilfellene klassifiseres den som den først passende. I en urettet graf får vi bare tre- og tilbake-kanter.
Visualisering av Klassifisering av Kanter Figuren under viser hvordan kantene i en graf kan klassifiseres utifra egenskapene til et dybde-først søk.
Topologisk Sortering Vi skal se på hvordan vi kan utføre et såkalt topologisk sortering av rettet graf uten sykler (directed acyclic graph) (DAG). Vi vil finne en lineær rekkefølge av noder slik at hvis en kant (u, v) E så må u komme før v. Algoritmen er egnet for å sortere strukturer og prosesser som har en delvis rekkefølge. a > b og b > c a > c Vi kan også ha a og b som vi ikke vet noe om rekkefølgen på. Topologisk sortering av en DAG kan alltid finne en total rekkefølge utifra en delvis rekkefølge.
Eksempel På Delvis Rekkefølge Figuren under viser en graf som har en delvis rekkefølge.
Pseudokode for Topological-Sort Pseudokoden for Topological-Sort er listet under Pseudokoden impliserer en sortering av nodene på dets avslutningstid. Dette er strengt tatt ikke nødvendig. Vi kan skrive ut nodene direkte når de avsluttes. Da vil rekkefølgen vi er ute etter være den omvendte av det som blir skrevet ut. Vi kan legge til avsluttede noder på begynnelsen av en lenket liste.
Hvordan Topological-Sort Fungerer Figuren under viser en graf som har en delvis rekkefølge samt den lineære rekkefølgen som Topological-Sort genererer.
Analyse av Topological-Sort Siden algoritmen er identisk med DFS bortsett fra utskrift/innsetting av fullførte noder, så vil også kjøretiden være den samme. Kjøretiden for Topological-Sort er Θ(V + E).
Korrektheten til Topological-Sort For å bevise at Topological-Sort er korrekt må vi bare bevise at hvis (u, v) E så må v.f < u.f. Når vi utforsker (u, v) så må u være grå, og v en av følgende. Hvis v er hvit så blir v en etterkommer av u og da vet vi at v.f < u.f. Hvis v er svart så er v allerede ferdig utforsket i.e. v.f < u.f v kan ikke være grå, for det vil gitt grafen en tilbake-kant, som ikke er mulig i en DAG (se fagboka).
Relasjonen Mellom Dybde-Først Søk og Backtracking Backtracking er en algoritmestrategi som er relatert til dybde-først søk. Vi prøver hver mulighet så snart de oppdages og går tilbake (backtrack) når vi når en situasjon som ikke kan lede til en løsning. Backtracking-løsninger er gjerne rekursive. Vi bygger en løsning inkrementelt Prøver mulighetene sekvensielt i hvert rekursive kall De potensielle muligheten kan sees som noder i en graf, og at de rekursive kallene er et søk gjennom grafen. Grafen må ikke alltid være eksplisitt. Den kan bygges etter behov.
Maze-Problemet Maze-problemet går ut på å finne en vei gjennom en labyrint gitt et startpunkt. Dette kan enkelt løses ved å utforske alle gyldige veier i labyrinten rekursivt. Hvert rekursive kall som utforsker en ny posisjon i labyrinten kan sees som en node i en graf med alle posisjonene som kan nås fra den posisjonen som nabonodene.
Dronning-Problemet Dronning-problemet er et problem med historisk klang. Problemet går ut på plassere n dronninger på et n n sjakkbrett slik at de ikke angriper hverandre. Dette problemet kan løses på mange ulike måter. Teste alle mulige kombinasjoner (veldig ineffektivt) Teste litt smartere ved å unngå plasseringer på samme rad og kolonne. Bygge løsningen inkrementelt med backtracking De mulige posisjonene for hver dronning kan sees som noder i en graf og backtracking algoritmen som en dybde-først søk.