Algoritmai ir duomenų struktūros (ADS) 7 paskaita Saulius Ragaišis, VU MIF saulius.ragaisis@mif.vu.lt 2015-04-13
Grafai Grafas aibių pora (V, L). V viršūnių (vertex) aibė, L briaunų (edge) aibė Briauna atkarpa, jungianti dvi grafo viršūnes. Pografis (subgraph) poaibis grafo briaunų bei jų viršūnių.
Grafai (2) Dvi viršūnės yra gretimos arba kaimyninės (adjacent), jei jos sujungtos briauna. Viršūnės V i ir V j yra kaimyninės, jei egzistuoja B k =(V i, V j ). Pvz.: A kaimyninės viršūnės yra B ir D. Plokščias arba planarinis grafas tai grafas, kuri galima nupiešti plokštumoje (bent vienu būdu) taip, kad nė viena pora briaunų nesikirstų.
Grafai (3) Kelias (path) tarp viršūnių briaunų seka, prasidedanti vienoje viršūnėje ir besibaigianti kitoje viršūnėje. Paprastas kelias (simple path) kelias, per kiekvieną jam priklausančią viršūnę einantis tik po vieną kartą. Pvz., kelias ADCBCE nėra paprastas kelias, nes per viršūnę C eina du kartus. Ciklas (cycle) paprastas kelias, kuris prasideda ir baigiasi toje pačioje viršūnėje. Pvz., ABCDA.
Grafai (4) Jungus grafas (connected) jei egzistuoja kelias tarp bet kurių viršūnių porų. V i, V j : kelias V i V j Pilnas grafas (complete) jei yra briauna tarp kiekvienos viršūnių poros. V i, V j : B = (V i, V j ) Aišku, kad pilnas grafas taip pat yra ir jungus, tačiau jungus grafas nebūtinai yra pilnas. Kiek briaunų gali būti tarp 2 viršūnių?
Grafai su svoriais Grafas su svoriais (weighted) grafas, kurio briaunos turi skaitines reikšmes (svorius).
Orientuoti grafai Lankas briauna, turinti kryptį. Orientuotas grafas (directed) grafas su lankais (visos briaunos turi kryptį). Kiek lankų gali būti tarp 2 viršūnių?
Orientuoti grafai (2) Pvz.: Knygų skolinimasis: A iš B pasiskolino 100 knygų, o B iš A pasiskolino 50 knygų. Visi apibrėžimai, kurie buvo taikomi neorientuotiems grafams, taip pat tinka ir orientuotam grafui. Pvz.: Orientuotas kelias yra seka lankų tarp dviejų viršūnių. Būtina pastebėti, kad orientuotame grafe galima situacija: A yra kaimynas B, bet B nėra A kaimynas.
ADT Grafas Pagrindinės operacijos su grafais kaip ADT: Sukurti tuščią grafą. Įdėti/išmesti viršūnę. Įdėti/išmesti briauną tarp viršūnių V 1 ir V 2. Sužinoti (rasti), ar yra kelias tarp viršūnių V 1 ir V 2. Sužinoti (V 1, V 2 ) svorį. Pakeisti (V 1, V 2 ) svorį.
Grafo realizavimas Yra du dažniausiai naudojami grafų realizavimo būdai: kaimynystės matrica kaimynystės sąrašai Abiem atvejais patogiausia įsivaizduoti, kad viršūnės numeruojamos 1, 2 ir taip toliau iki N.
Kaimynystės matrica Kaimynystės matrica grafui be svorių su N viršūnių yra N iš N loginis masyvas A toks, kad A[i, j] yra teisingas tada ir tik tada, kai egzistuoja briauna iš viršūnės i į viršūnę j. Pagal susitarimą A[i, i] yra klaidingas. Įsidėmėtina, kad kaimynystės matrica neorientuotam grafui yra simetriška, tai yra A[i, j] = A[j, i]. Neorientuotas grafas (simetriška matrica) Orientuotas grafas (dažniausiai nesimetriška matrica)
Kaimynystės matrica (2) Kai turim grafą su svoriais, yra patogu, kad A[i, j] būtų briaunos iš viršūnės i į viršūnę j svoris. Tada A[i, j] žymima, kai nėra briaunos iš viršūnės i į viršūnę j. Be to, įstrižainės A[i, i] reikšmės lygios 0.
Kaimynystės sąrašai Kaimynystės sąrašas grafo iš N viršūnių, kurios numeruojamos 1, 2,, N, susideda iš N sujungtų sąrašų. Jei grafas yra su svoriais, tai jie saugomi kartu su viršūnę. Pvz.:
Grafo realizacijų palyginimas Dvi dažniausiai naudojamos grafų operacijos yra: Duotos dvi viršūnės i ir j ; rasti, ar yra briauna iš i į j. Rasti visas viršūnes, kurios yra kaimynės duotajai viršūnei V i Jei grafas yra netoli pilno grafo, tai masyvas yra efektyvesnis už sąrašą. Jei briaunų mažai, tai lieka daug nepanaudotos vietos matricoje, kas yra minusas taupant, tuomet geriau sąrašas.
Grafo apėjimas (traversal) Egzistuoja du apėjimo algoritmai: į gylį (DFS Depth First Search); į plotį (BFS Breadth First Search).
DFS pseudo-kodas {S stekas} Push(S, v) MarkV(v) {pažymi aplankytą viršūnę} While (not IsEmpty(S)) { If (neegzistuoja neaplankyta kaimynė S viršūnei) then Pop(S) else { imame u S viršūnės kaimynę (u ϵ V) Push(S, u) MarkV(u) } }
Grafo apėjimo DFS būdu pavyzdys
BFS pseudo-kodas {Q eilė} Add(Q, V) {įdedame viršūnę V į eilę} MarkV(V) {pažymi aplankytą viršūnę} While (not IsEmpty(Q)) do { } w:= Get(Q) for w neaplankytai kaimynei u do { MarkV(u) } Add(Q, u)
Topologinis rikiavimas Taikomas orientuotam grafui be ciklų. Pvz.: briaunos išreiškia, koks dalykas prieš kokį dalyką turi būti išklausytas. Prieš dalyką G reikia išklausyti B. Du variantai: ABCGP ir ABGCP.
Topologinio rikiavimo algoritmai Paprastas algoritmas (pa): 1. Imti viršūnę iš kurios nėra išeinančių briaunų. 2. Įdėti ją į sąrašo pradžią ir iš grafo ją išmesti. Modifikuotas paprastas algoritmas (pam): 1. Imti viršūnę į kurią nėra įeinančių briaunų. 2. Įdėti ją į sąrašo galą ir iš grafo ją išmesti.
Klausimai?