Datastrukturer föreläsning 7 Maps 1
Grafer Maps 2
Grafer ett exempel En oriktad graf: Noderna är flygplatser (trebokstavskombinationer) Det finns en båge mellan två noder omm det finns en flyglinje mellan motsvarande flygplatser. Till varje båge finns dessutom ett tal som representerar avståndet mellan flygplatserna. PVD ORD SFO LGA HNL 337 LAX 1843 1233 802 DFW 849 1120 MIA Maps 3
Riktade och oriktade grafer I en riktad graf har bågarna en riktning. I en oriktad graf saknar bågarna riktning. Exempel. - Ett vägnät med enkelriktade gator kan representeras som en riktad graf - Ett vägnät utan enkelriktade gator kan representeras som en oriktad graf - Obs att en oriktad graf kan ses som ett specialfall av en riktad graf! Maps 4
Vad är en graf, matematiskt? En riktad graf är ett par (V,E) där V är en mängd av noder (hörn) E C VxV är en mängd av ordnade par av noder som kallas bågar (kanter). Om (v,w) är en båge kallas v bågens källa och w bågens mål. Det kan dessutom finnas ytterligare information om bågen, t ex en vikt eller ett namn. En oriktad graf definieras på samma sätt som en riktad graf, med den enda skillnaden att bågarna är oordnade par. Om (v,w) är en båge i en oriktad graf kallar vi v och w bågens ändpunkter. De oriktade graferna kan betraktas som symmetriska riktade grafer, dvs riktade grafer med egenskapen att om (v,w) är en båge i E så är också (w,v) en båge i E. Maps 5
Riktade och oriktade bågar Riktade bågar ordnade par av bågar (u,v) u är källan (ursprungsnoden) v är målet (målnoden) Exempel: bågar är flyglinjer från en flygplats till en annan. Vi har här dessutom information om flyglinjens nummer i bågen. Oriktade bågar oordnade par av bågar (u,v) Exempel: bågar finns mellan flygplatser som har en flyglinje mellan sig. Det finns dessutom information om avståndet mellan flygplatserna. En riktad graf har riktade bågar En oriktad graf har oriktade bågar ORD ORD flight AA 1206 849 miles PVD PVD Maps 6
Fler exempel Elektriska kretsar Vägnät Flygnätverk Flödesscheman Datanätverk Local area network Internet Databaser Entity-relationship diagram Maps 7
Terminologi Ändpunkter U och V är ändpunkter på a Bågar som är förbundna med (eller utgår från) noder a, d, b är förbundna med V Grannoder U och V är grannar En nods grad X har graden 5 Self-loop j är en self-loop Parallella bågar h och i är parallella bågar U a c V W d f b e X Y g h i Z j Maps 8
Mer terminologi Väg Alternerande följd av noder och bågar Börjar och slutar med nod Varje båge kommer mellan sina ändpunktsnoder Om det inte finns parallella bågar räcker det att ange en följd av noder! Enkel väg Exempel Alla noderna är distinkta P 1 =(V,b,X,h,Z) är en enkel väg P 2 =(U,c,W,e,X,g,Y,f,W,d,V) är inte någon enkel väg U a c V d P 2 W f b e P 1 X g Y h Z Maps 9
Ännu mer terminologi Cykel: väg som börjar och slutar i samma nod Enkel cykel: noderna på cykeln är distinkta utom startnoden = slutnoden Exempel: C 1 =(V,b,X,g,Y,f,W,c,U,a,V) är en enkel cykel C 2 =(U,c,W,e,X,g,Y,f,W,d,V,a,V ) är en cykel som inte är enkel (W besöks två gånger) U a c V d C 2 W f b X e Y C 1 g h Z Maps 10
Egenskaper hos oriktade grafer Egenskap 1 Σ v deg(v) = 2m Bevis: varje ändpunkt räknas två gånger Egenskap 2 Om self-loops och parallella bågar saknas gäller m n (n 1)/2 Bevis: en nods grad är högst (n 1). Notation n m deg(v) antalet noder antalet bågar graden hos v Exempel n = 4 m = 6 deg(v) = 3 Maps 11
Hur implementerar man grafer? Det finns tre olika huvudmetoder! - båglista - grannmatris - grannlistor Maps 12
Båglista som implementeringsmetod Grafen implementeras som en lista av noder och en lista av bågar med deras ändpunkter (källor och mål) Denna lista kan implementeras som ett fält eller en länkad lista Problem: om vi befinner oss i en nod måste vi leta genom hela båglistan för att hitta dess grannar Maps 13
Grannmatris (kopplingsmatris) Numrera noderna Grafen implementeras med hjälp av en matris M, så att M[i,j] är 1 om det finns en båge mellan noderna med nummer i och j och 0 annars. (Man kan också lagra information om bågen i M[i,j].) Effektivt (O(1)) att avgöra om två noder är grannar, men utrymmet är O(n 2 ). Bra för grafer med många bågar. Maps 14
Grannlistor En lista av par (v,vs) där v är en nod och vs är en lista som innehåller par av grannoder till v och bågarna som går till dem. Listan kan implementeras som ett fält eller en länkad lista. (om grafen är stor kan det även vara lämpligt att använda effektiva datastrukturer som hashtabeller) Bra metod om man enkelt vill kunna hitta en viss nods grannar. Maps 15
Grafrepresentation i Haskell Riktad graf utan information i noderna. Nod och bågmängder implementerade som listor. Båglista type Graph = ([Node],[Edge]) type Edge = (Node,Node) Grannlistor type Graph = [(Node,[Node])] Maps 16
En ADT för riktade grafer Metoder för att få ut information om grafen incidentedges(v) origin(e) destination(e) areadjacent(v, w) Metoder för att ändra grafen insertvertex(v) insertedge(v, w, e) removevertex(v) removeedge(e) Allmänna metoder numvertices() numedges() vertices() edges() Maps 17
Delgrafer En delgraf S till en graf G S noder är en delmängd av Gs S kanter är en delmängd av Gs En uppspännande delgraf till G innehåller alla Gs noder delgraf uppspännande delgraf Maps 18
Sammanhängande En graf är sammanhängande om varje par av noder i grafen är förbundna med en väg En sammanhängande komponent av G är en maximal sammanhängande delgraf av G sammanhängande graf osammanhängande graf med två sammanhängande komponenter Maps 19
Fria träd och skogar Ett fritt träd är en oriktad graf som är sammanhängande saknar cykler Obs att fria träd saknar rot! En skog är en oriktad graf som saknar cykler En sammanhängande komponent i en skog är träd fritt träd skog Maps 20
Uppspännande träd och skogar Ett uppspännande träd för en sammanhängande graf är en uppspännande delgraf som är ett fritt träd En graf kan ha mer än ett uppspännande träd Tillämpning: kommunikationsnätverk En uppspännande skog är en uppspännande delgraf som är en skog graf uppspännande träd Maps 21
Djupet-först sökning (DFS) och bredden-först sökning (BFS) Två metoder att genomsöka en graf; två grafiteratorer! Kan även användas för att avgöra om två noder är sammanbundna. Djupet först: välj en startnod, följ en väg så långt som möjligt, gör sedan backtracking, följ nästa väg så långt som möjligt, osv Bredden först: välj en startnod, genomsök först alla noder med avståndet 1, sedan alla noder med avståndet 2, osv. Lecture 6 22
Djupet-först sökning A B D E C Lecture 6 23
Exempel A obesökt nod A A besökt nod obesökt båge upptäcktsbåge bakåtbåge B C D E A A B D E B D E C C Lecture 6 24
Exempel, fortsättning A A B D E B D E C C A A B D E B D E C C Lecture 6 25
Djupet-först sökning av en labyrint Nod = korsning, hörn eller slut på återvändsgränd Båge = korridor Rekursionsstack för backtracking = rep tillbaka till ingången Lecture 6 26
DFS-algoritmen Algoritmen markerar besökta noder och upptäcktsbågar, dvs den bygger ett DFS-träd. Dessutom markerar den bakåtbågar. Algorithm DFS(G) Input graph G Output labeling of the edges of G as discovery edges and back edges for all u G.vertices() setlabel(u, UNEXPLORED) for all e G.edges() setlabel(e, UNEXPLORED) for all v G.vertices() if getlabel(v) = UNEXPLORED DFS(G, v) Algorithm DFS(G, v) Input graph G and a start vertex v of G Output labeling of the edges of G in the connected component of v as discovery edges and back edges setlabel(v, VISITED) for all e G.incidentEdges(v) if getlabel(e) = UNEXPLORED w opposite(v,e) if getlabel(w) = UNEXPLORED setlabel(e, DISCOVERY) DFS(G, w) else setlabel(e, BACK) Lecture 6 27
DFS: egenskaper Egenskap 1 DFS(G, v) besöker alla noder i vs sammanhängande komponent A Egenskap 2 Upptäcktsbågarna som markeras av DFS(G, v) utgör ett uppspännande träd för vs sammanhängande komponent ett DFS-träd B C D E Lecture 6 28
Analys av DFS Varje nod markeras två gånger En gång som UNEXPLORED En gång som VISITED Varje båge markeras två gånger En gång som UNEXPLORED En gång som DISCOVERY eller BACK Metoden incidentedges anropas en gång för varje nod Exekveringstiden för DFS är O(n + m) om grafen är implementerad som en grannlista Kom ihåg att Σ v deg(v) = 2m Lecture 6 29
Tidskomplexitet i flera variabler När vi introducerade O-komplexitet talade vi bara om funktioner av en variabel (ofta storleken hos indata kallad n ). Vi förklarade betydelsen av O(n), O(n 2 ), O(log n), O(n log n) osv Ibland är det naturligt att mäta indatastorleken i flera variabler, t ex * Matrismultiplikation av m*n och n*p matriser har komplexiteten O(mnp) * Djupet först sökning av en graf med n noder och m bägar Maps 30 har komplexiteten O(m+n)
Definition av O(f(m,n)) Definitionen är analog med envariabelfallet: T(m,n) är O(f(m,n)) omm det finns C och n 0 så att T(m,n) < Cf(m,n) för n > n 0 T ex T(m,n) är O(m+n) omm det finns C och n 0 så att T(m,n) < C(m+n) för n > n 0 Maps 31
Vanlig fråga: Kan vi inte förenkla O(mnp) till O(n 3 )? Nej, komplexiteten beror inte bara på n utan också på m och p! Eller till O(k 3 )? Vad skulle k vara? Jo, om t ex k är den maximala dimensionen (k = max(m,n,p)). Vi har alltså att matrismultiplikation är O(max(m,n,p) 3 ). Maps 32
Samma fråga om djupet först: Kan vi inte förenkla O(m+n) till O(n) eller O(m)? Nej, komplexiteten beror inte bara på antalet noder eller antalet bågar; den beror på båda! Notera att O(m+n) = O(max(m,n)). Varför? I specialfall, t ex, sammanhängande graf utan parallella bågar har vi att m är O(n 2 ). I så fall kan vi dra slutsatsen att djupet först sökning är O(n 2 ). Men detta är mindre informativt, tänk om vi har har en gles graf med färre bågar än noder! Då har vi ju faktiskt O(n)! Maps 33
Tids- och utrymmeskomplexitet n noder m bågar inga parallella bågar inga self-loops riktad graf utrymme incidentedges(v) areadjacent (v, w) insertvertex(v) insertedge(v, w, e) båglista grannlista grannmatris Maps 34
Tids- och utrymmeskomplexitet n noder m bågar inga parallella bågar inga self-loops riktad graf båglista grannlista grannmatris utrymme O(n + m) O(n + m) O(n 2 ) incidentedges(v) areadjacent (v, w) insertvertex(v) insertedge(v, w, e) Maps 35
Tids- och utrymmeskomplexitet n noder m bågar inga parallella bågar inga self-loops riktad graf båglista grannlista grannmatris utrymme O(n + m) O(n + m) O(n 2 ) incidentedges(v) O(m) O(deg(v)) O(n) areadjacent (v, w) insertvertex(v) insertedge(v, w, e) Maps 36
Tids- och utrymmeskomplexitet n noder m bågar inga parallella bågar inga self-loops riktad graf båglista grannlista grannmatris utrymme O(n + m) O(n + m) O(n 2 ) incidentedges(v) O(m) O(deg(v)) O(n) areadjacent (v, w) O(m) O(deg(v)) O(1) insertvertex(v) insertedge(v, w, e) Maps 37
Tids- och utrymmeskomplexitet n noder m bågar inga parallella bågar inga self-loops riktad graf båglista grannlista grannmatris utrymme O(n + m) O(n + m) O(n 2 ) incidentedges(v) O(m) O(deg(v)) O(n) areadjacent (v, w) O(m) O(deg(v)) O(1) insertvertex(v) O(1) O(n) O(n 2 ) insertedge(v, w, e) Maps 38
Tids- och utrymmeskomplexitet n noder m bågar inga parallella bågar inga self-loops riktad graf båglista grannlista grannmatris utrymme O(n + m) O(n + m) O(n 2 ) incidentedges(v) O(m) O(deg(v)) O(n) areadjacent (v, w) O(m) O(deg(v)) O(1) insertvertex(v) O(1) O(n) O(n 2 ) insertedge(v, w, e) O(1) O(1) O(1) Maps 39
Dynamiska fält och grannmatriser En grannmatris är ett fält. För att kunna lägga till nya element utan att riskera overflow måste vi använda ett dynamiskt fält. Obs att insättning av ny node ( insertvertex i tabellen) då får O(1) som amorterad komplexitet, men O(n 2 ) som vanlig värstafallskomplexitet. Maps 40
Dynamiska fält och grannlistor I tabellen har vi antagit att grannlistorna är implementerade som ett dynamiskt fält av länkade listor. Då får vi snabb åtkomst av grannarna till en given nod. Hur ändrar sig komplexiteterna i tabellen om vi har grannlistan som en länkad lista av länkade listor? Maps 41
Djupet-först sökning: tillämpningar Avgör om en graf är sammanhängande Bestäm de sammanhängande komponenterna Bestäm en uppspännande skog Finn en väg mellan två noder Finn en cykel Lecture 6 42
Bredden-först sökning L 0 A L 1 B C D L 2 E F Lecture 6 43
Exempel A A obesökt nod besökt nod obesökt båge upptäcktsbåge övergångsbåge L 1 L 0 B A E C F D L 0 A L 0 A L 1 B C D L 1 B C D E F E F Lecture 6 44
Exempel (forts.) L 0 A L 0 A L 1 B C D L 1 B C D E F L 2 E F L 0 A L 0 A L 1 B C D L 1 B C D L 2 E F L 2 E F Lecture 6 45
Exempel forts. L 0 A L 0 A L 1 B C D L 1 B C D L 2 E F L 2 E F L 0 A L 1 B C D L 2 E F Lecture 6 46
BFS-algoritmen Algorithm BFS Input graph G Output labeling of the edges and partition of the vertices of G for all u G.vertices() setlabel(u, UNEXPLORED) for all e G.edges() setlabel(e, UNEXPLORED) for all v G.vertices() if getlabel(v) = UNEXPLORED BFS(G, v) Algorithm BFS(G,s) L 0 new empty sequence L 0.insertLast(s) setlabel(s, VISITED) i 0 while L i.isempty() L i +1 new empty sequence for all v L i.elements() for all e G.incidentEdges(v) if getlabel(e) = UNEXPLORED w opposite(v,e) if getlabel(w) = UNEXPLORED setlabel(e, DISCOVERY) setlabel(w, VISITED) L i +1.insertLast(w) else setlabel(e, CROSS) i i +1 Lecture 6 47
Bredden först sökning Exekveringstiden för BFS på en graf med n noder och m bågar är O(m+n) BFS kan användas För att hitta kortaste vägen (i en oviktad graf) mellan två noder Se även tillämpningarna för DFS (finna sammanhängande komponenter, cykler, etc) Maps 48
Den kortaste vägen 0 8 A 4 2 8 B 7 2 C 1 D 2 5 3 9 8 E F 5 3 Lecture 6 49
Viktade grafer I en viktad graf tillordnar vi ett tal till varje båge. Detta tal kallas en vikt Vikter kan representera avstånd, kostnader mm Exempel: avstånd mellan flygplatser SFO 337 1843 ORD 802 849 LGA PVD 1205 HNL LAX 1233 DFW 1120 MIA Lecture 6 50
Att finna kortaste vägen Givet en viktad graf och två noder u och v, finn en väg mellan dem vars bågar har minimal sammanlagd vikt Tillämpningar Färdplaner för flyg, tåg, bilar, osv Snabbaste vägen att skicka ett paket över internet Exempel: HNL Kortaste vägen mellan PVD och HNL SFO 337 LAX 1843 1233 ORD 802 DFW 849 1120 LGA PVD MIA Lecture 6 51 1205
Hur man finner kortaste vägen mellan två noder i en riktad graf Dijkstras algoritm är en generalisering av BFS som beräknar kortaste vägar i en viktad graf. Den besöker noderna i avståndsordning från startnoden. Den beräknar även avståndet från startnoden till alla andra noder. Lecture 6 52
DFS, BFS och Dijkstras algoritm Dessa tre algoritmer delar in noderna i besökta, kandidatnoder (grannar till besökta noder), och obesökta noder. DFS har en stack med kandidatnoder BFS har en kö med kandidatnoder Dijkstras algoritm har en prioritetskö med kandidatnoder Obs. Kön i pseudokoden för BFS är implicit! Lecture 6 53
Exempel: kortaste vägar från noden A till övriga noder 0 8 A 4 2 B 7 C 1 D 3 9 2 E F 5 Besökta noder: 0 Prioritetskö Q: (0,A) Lecture 6 54
Steg 1: besök A och lägg dess grannar i Q! 8 A 4 8 2 2 4 7 1 B C D 3 9 2 5 E F Besökta noder: 1 Prioritetskö Q:(2,C) (4,D) (8,B) Lecture 6 55
Steg 2 8 A 4 8 2 2 3 7 1 B C D 5 3 9 11 2 5 E F Besökta noder: 2 Prioritetskö Q: (3,D)(5,E)(8,B)(11,F) Besök C och lägg till grannarna E och F som inte redan finns i Q. Uppdatera också avståndet till D eftersom en kortare väg från startnoden A har hittats. Lecture 6 56
Steg 3 8 A 4 8 2 2 3 7 1 B C D 5 3 9 8 2 5 E F Besökta noder: 3 Prioritetskö Q: (5,E)(8,B)(8,F) Nu är alla noder antingen besökta eller ligger i Q. Vi måste dock uppdatera avståndet till F. Lecture 6 57
Steg 4 8 A 4 7 2 2 3 7 1 B C D 5 3 9 8 2 5 E F Besökta noder: 4 Prioritetskö Q: (7,B)(8,F) Nu uppdaterade vi avståndet till B. Lecture 6 58
Steg 5 8 A 4 7 2 2 3 7 1 B C D 5 3 9 8 2 5 E F Besökta noder: 5 Prioritetskö Q: (8,F) Lecture 6 59
Steg 6 8 A 4 7 2 2 3 7 1 B C D 5 3 9 8 2 5 E F Besökta noder: 6 Q: tom Lecture 6 60
Hur man implementerar Dijkstras algoritm Input: en graf G med icke-negativa vikter och en startnod s Output: För varje nod u det kortaste avståndet D[u] från s. Från början sätter vi D[s] till 0 och D[u] till oändligheten. Under exekveringen av algoritmen kommer D[u] att innehålla de hittills funna kortaste avstånden från s. Algoritmen använder sig av en prioritetskö Q som innehåller alla obesökta noder u med D[u] som prioriteter. Vi besöker den nod som har högst prioritet i Q. Om vi vill returnera kortaste vägar och inte bara kortaste avstånd låter vi D[u] även innehålla en pekare till föregående nod på den kortaste vägen. Om vi vill kunna uppdatera prioriteten i Q för en viss nod behöver vi dessutom lagra platsen som noden lagras på i Q. (Om Q är en heap så lagrar vi index i fältet som lagrar Q.) Lecture 6 61
Dijkstras algoritm Algorithm ShortestPath(G,s) D[s] = 0, D[u] = infinity for all nodes u different from s. Q new priority queue containing all nodes u with priorities D[u] while Q.isEmpty() u Q.removeMinNode() ( visit u) for each node z adjacent to u and not yet visited do if D[u] + weight(u,z) < D[z] then D[z] D[u] + weight(u,z) and update the priority of z in Q return D[u] for each node u En implementeringsdetalj: Q i exemplet tidigare visar inte de avstånd D[u] som är oändligheten. En alternativ implementering har inte dessa med i Q. Lecture 6 62
Några egenskaper Egenskap 1: En delväg till en kortaste väg är också en kortaste väg Egenskap 2: Det finns ett träd av kortaste vägar från en startnod till de alla de andra noderna Exempel: Träd med kortaste vägar från PVD SFO ORD LGA PVD HNL 337 1843 802 849 1205 LAX 1233 DFW 1120 MIA Lecture 6 63
Komplexiteten hos Dijkstra med heap Om grafen har n noder och m bågar och vi implementerar Q med en uppdaterbar heap gäller att Heapmetoderna (ta bort minsta och ändra prioriteten på ett element i Q) är O(log n). Man tar bort minsta elementet n gånger Man ändrar en prioritet för någon nod maximalt en gång för varje båge, dvs O(m). Alltså är komplexiteten O((m+n)log n) Lecture 6 64
Komplexiteten hos Dijkstra med Q som fält Om vi i stället implementerar Q med ett osorterat fält av noder och grafen har n noder och m bågar är Att ta bort minsta elementet är O(n) och man gör detta maximalt n gånger. Totala tiden för denna operation är alltså O(n 2 ). Att ändra prioriteten på ett element är O(1) och man gör detta maximalt en gång för varje båge. Totala tiden för denna operation är alltså O(m). Alltså är komplexiteten O(n 2 + m). Detta är bättre än O((m+n)log n) om vi har en tät graf. Lecture 6 65
Heuristisk sökning Om man letar efter en specifik nod i en graf kan man förbättra Dijkstras algoritm om man har ytterligare heuristisk information T ex kan man uppskatta tiden det tar att åka till en viss hållplats om man vet det geografiska avståndet ( as the crow flies ) När man väljer kandidatnod rankar man noderna efter summan av tiden från utgångspunkten och den uppskattade tiden till målet Denna algoritm kallas A* (brukar betraktas som AI) Heuristik = tumregel Lecture 6 66