520 likes | 613 Views
Dijkstra algoritmus Minimális költségű feszítőfák Fák alulról felfelé. Kupac. 1. 6. 2. 3. 7. 4. 8. 5. A kupac olyan véges elemsokaság, amely rendelkezik az alábbi tulajdonságokkal:
E N D
Dijkstra algoritmus Minimális költségű feszítőfák Fák alulról felfelé
Kupac 1 6 2 3 7 4 8 5 A kupac olyan véges elemsokaság, amely rendelkezik az alábbi tulajdonságokkal: • Minden elemnek legfeljebb két rákövetkezője (leszármazottja) lehet. Azaz bináris fának tekinthető. • Minden eleme kisebb (vagy egyenlő) a közvetlen leszármazottainál. • Akupacbalról folytonos, azaz ha nem teljes a fa, akkor csak a leg-utolsó szintből hiányozhatnak elemek, de azok is csak a szint jobb széléről. Ezek következménye, hogy ábrázolhatófolytonosan is, tömbben. Gráfok - fák
Kupac Műveletei: Üres, üres?, első, Felcsúsztat, Lecsúsztat, Kupacba, Kupacból Üres: Kupac üres?(Kupac): Logikai első(Kupac): Elem {NemDef} Kupacba(Kupac,Elem): Kupac {NemDef} Kupacból(Kupac,Elem): (Kupac Elem) {NemDef} Felcsúsztat(Kupac,Index): Kupac Lecsúsztat(Kupac,Index): Kupac Gráfok - fák
Kupac Kupac ábrázolása: Rekord(N: Egész; t: Tömb(1..MaxN:Elemtípus), hiba: Logikai) Gráfok - fák
Kupac Műveletek megvalósítása: Üres(K): K.N:=0 Eljárás vége. üres?(K): üres?:=(K.N=0) Függvény vége. első(K): első:=K.t(1) Függvény vége. Gráfok - fák
Kupac 1 1 1 1 6 6 6 6 3 2 3 3 5 3 5 2 7 7 7 7 4 4 4 4 8 8 8 8 2 5 5 Elem berakás: Kupacba([1,3,6,5,4,7,8],2) [1,2,6,3,4,7,8,5] Felcsúsztatás: Elemberakás Gráfok - fák
Kupac Kupacba(K,e): K.N:=K.N+1; K.t(K.N):=e; Felcsúsztat(K,K.N) Eljárás vége. Felcsúsztat(K,i): Ha i>1 akkor Ha K.t(i)<K.t(i div 2) akkor Csere(K.t(i),K.t(i div 2)) Felcsúsztat(k,i div 2) Eljárás vége. Kupacból(K,e): e:=K.t(1); K.t(1):=K.t(K.N); K.N:=K.N-1Lecsúsztat(K,1) Eljárás vége. Gráfok - fák
Kupac 1 5 2 6 6 2 2 6 5 3 3 7 7 4 4 8 8 3 7 4 8 5 2 6 3 5 7 4 8 Elemkivétel: Kupacból([1,2,6,3,4,7,8,5]) (1,[2,3,6,5,4,7,8]) Elemkiolvasás „Utolsó előre fuss!” Előrehozás + lecsúsztatás: Gráfok - fák
Kupac Lecsúsztat(K,i): Ha i≤K.N div 2 akkor j:=kisebb(2*i,2*i+1) Ha K.t(i)>K.t(j) akkor Csere(K.t(i),K.t(j)) Lecsúsztat(K,j) Eljárás vége. kisebb(j,k): Ha k>K.N vagy K.t(j)≤K.t(k) akkor kisebb:=j különben kisebb:=k Eljárás vége. 6 3 7 5 8 Gráfok - fák
Kupac Műveletigény: Lecsúsztat = Kupacból: O(log2(N)) Felcsúsztat = Kupacba: O(log2(N)) Használjuk a kupacot rendezésre! Rendezési idő: O(N*log2(N)) Gráfok - fák
Kupacrendezés Rendez(X): Üres(K) Ciklus i=1-től N-ig Kupacba(K,X(i)) Ciklus vége Ciklus i=1-től N-ig Kupacból(K,X(i)) Ciklus vége Eljárás vége. Gráfok - fák
Prioritási sor Prioritási sor: speciális sorozat Mindig a legfontosabb (minimális vagy maximális) lép ki belőle. Emlékeztető: időrendbeli tárolás (kb.) Sorba – végére – O(1), Sorból – minimumkiválasztás, majd az utolsó a minimum helyére – O(N) nagyság szerinti tárolás Sorba – beillesztés a helyére – O(N), Sorból – elejéről – O(1) Gráfok - fák
Prioritási sor Prioritási sor megvalósítása kupaccal Ötletek: A prioritási sor speciális kupac, ahol elemek sorszámát tá-roljuk, egy prioritás tömbben pedig a prioritásukat. (Ha egyéb jellemzőjük lenne, azt is külön tárolnánk.) A prioritási sor speciális kupac, ahol az elemek rekordok, s az egyik mezőjük a prioritás. Gráfok - fák
Prioritási sor Prioritási sor ábrázolása (kupac+prioritás tömb): Rekord(N: egész, t: Tömb(1..MaxN: Elemtípus), pr: Tömb(1..MaxN:Egész)) Műveletei: Üres, üres?, PrSorba, PrSorból, első Megoldás: újraírjuk a kupac műveleteit. Gráfok - fák
Prioritási sor Műveletek megvalósítása: Üres(P): P.N:=0 Eljárás vége. üres?(P): üres?:=(P.N=0) Függvény vége. első(K): első:=P.t(1) Függvény vége. Gráfok - fák
Prioritási sor PrSorba(P,e,pr): P.N:=P.N+1; P.t(P.N):=e; P.pr(e):=pr Felcsúsztat(P,P.N) Eljárás vége. PrSorból(P,e,pr): e:=P.t(1); pr:=P.pr(e); P.t(1):=P.t(P.N) P.N:=P.N-1; Lecsúsztat(P,1) Eljárás vége. Gráfok - fák
Prioritási sor Felcsúsztat(P,i): Ha i>1 akkor Ha P.pr(P.t(i))<P.pr(P.t(i div 2)) akkor Csere(P.t(i),P.t(i div 2)) Felcsúsztat(k,i div 2) Eljárás vége. Gráfok - fák
Prioritási sor Lecsúsztat(P,i): Ha i≤P.N div 2 akkor j:=kisebb(2*i,2*i+1) Ha P.pr(P.t(i))>P.pr(P.t(j)) akkor Csere(P.t(i),P.t(j)) Lecsúsztat(P,j) Eljárás vége. kisebb(j,k): Ha k>P.N vagy P.pr(P.t(j))≤P.pr(P.t(k)) akkor kisebb:=j különben kisebb:=k Eljárás vége. Gráfok - fák
Prioritási sor Prioritási sor ábrázolása (kupac rekord elemekkel): Rekord(N: egész, t: Tömb(1..MaxN: Elemtípus)) Elemtípus=Rekord(pr: Egész, egyéb: Egyébtípus) Műveletei: Üres, üres?, PrSorba, PrSorból, első Megoldás: újraírjuk a kupac műveleteit. Gráfok - fák
Prioritási sor Műveletek megvalósítása: Üres(P): P.N:=0 Eljárás vége. üres?(P): üres?:=(P.N=0) Függvény vége. első(K): első:=P.t(1) Függvény vége. Gráfok - fák
Prioritási sor PrSorba(P,e): P.N:=P.N+1; P.t(P.N):=e Felcsúsztat(P,P.N) Eljárás vége. PrSorból(P,e): e:=P.t(1); P.t(1):=P.t(P.N); P.N:=P.N-1 Lecsúsztat(P,1) Eljárás vége. Gráfok - fák
Prioritási sor Felcsúsztat(P,i): Ha i>1 akkor HaP.t(i).pr<P.t(i div 2).pr akkor Csere(P.t(i),P.t(i div 2)) Felcsúsztat(P,i div 2) Eljárás vége. Gráfok - fák
Prioritási sor Lecsúsztat(P,i): Ha i≤P.N div 2 akkor j:=kisebb(2*i,2*i+1) Ha P.t(i).pr>P.t(j).pr akkor Csere(P.t(i),P.t(j)) Lecsúsztat(P,j) Eljárás vége. kisebb(j,k): Ha k>P.N vagy P.t(j).pr≤P.t(k).pr akkor kisebb:=j különben kisebb:=k Eljárás vége. Gráfok - fák
Prioritási sor Prioritási sor megvalósítása kupaccal – értékelés A prioritási sor speciális kupac, ahol elemek sorszámát tároljuk, egy prioritás tömbben pedig a prioritásukat. Csak akkor alkalmazható, ha az elemek sorszámozhatók. Gazdaságos az elemek kupacban való mozgatása miatt. A prioritási sor speciális kupac, ahol az elemek rekordok, s az egyik mezőjük a prioritás. Egyszerűbb megvalósítás, nem sorszámozható elemekre is. Lassú lehet hosszú elemek mozgatása a kupacban. Gráfok - fák
Prioritási sor Módosítható prioritási sor ábrázolása (kupac + prioritás tömb + index tömb): Rekord(N: egész, t: Tömb(1..MaxN: Elemtípus), pr: Tömb(1..MaxN: Egész), index: Tömb(1..MaxN: Egész)) Műveletei: Üres, üres?, PrSorba, PrSorból, első, Fel, Le A már sorban levő elemeket prioritásuk megváltozása esetén mozgatni kell. Gráfok - fák
Prioritási sor Műveletek megvalósítása: Üres(P): P.N:=0 Eljárás vége. üres?(P): üres?:=(P.N=0) Függvény vége. első(K): első:=P.t(1) Függvény vége. Gráfok - fák
Prioritási sor PrSorba(P,e,pr): P.N:=P.N+1; P.t(P.N):=e; P.pr(e):=pr P.index(e):=P.N; Felcsúsztat(P,P.N) Eljárás vége. PrSorból(P,e,pr): e:=P.t(1); pr:=P.pr(e); P.t(1):=P.t(P.N) P.N:=P.N-1; P.index(P.t(1)):=1;Lecsúsztat(P,1) Eljárás vége. Le(P,i): Lecsúsztat(P,P.index(i)) Eljárás vége. Gráfok - fák
Prioritási sor Lecsúsztat(P,i): Ha i≤P.N div 2 akkor j:=kisebb(2*i,2*i+1) Ha P.pr(P.t(i))>P.pr(P.t(j)) akkor Csere(P.t(i),P.t(j)) P.index(P.t(i)):=i P.index(P.t(j)):=j Lecsúsztat(P,j) Eljárás vége. Gráfok - fák
Prioritási sor Fel(P,i): Felcsúsztat(P,P.index(i)) Eljárás vége. Felcsúsztat(P,i): Ha i>1 akkor Ha P.pr(P.t(i))<P.pr(P.t(i div 2)) akkor Csere(P.t(i),P.t(i div 2)) P.index(P.t(i)):=i P.index(P.t(i div 2)):=i div 2 Felcsúsztat(P,i div 2) Eljárás vége. Gráfok - fák
Szélességi bejárás alkalmazásai Legrövidebb utak súlyozott gráfban • A szélességi bejárás megadja a legrövidebb utat, ha az út hosszán a benne szereplő élek számát értjük. • Ha az élek összhosszát, akkor azonban nem. • Ha minden él pozitív hosszúságú, akkor a kezdő-ponthoz legközelebbi pontba biztosan ismerjük a legrövidebb út hosszát. • A többi pontra pedig ismerjük az odavezető út hosszának egy felső korlátját. Mi a helyzet a negatív élekkel? Gráfok - fák
Szélességi bejárás alkalmazásai Legrövidebb utak súlyozott gráfban Abból a szürke pontból lépjünk tovább, ami a legköze-lebb van a kezdőponthoz – prioritási sor legelső eleme. A belőle elérhető pontokra számoljunk új felső korlá-tot: • a fehér pontokra a szürke távolságát megnöveljük az élhosszal – bekerül a prioritási sorba; • a szürke pontokra javítjuk a becslést az új távolsággal, ha lehetséges – mozog a prioritási sorban előre. Gráfok - fák
Szélességi bejárás alkalmazásai Szélességi bejárás(p): Szín(p):=szürke; PrSorba(p); Táv(p):=0 Ciklus amíg nem üresPrSor? PrSorból(p); Szín(p):=fekete Ciklus i=1-től Szomszédpontokszáma(p)-ig j:=Szomszéd(p,i) Ha Szín(j)=fehér akkor Táv(j):=Táv(p)+Élhossz(p,j) PrSorba(j); Szín(j):=szürke különben ha Táv(j)>Táv(p)+Élhossz(p,j) akkor Táv(j):=Táv(p)+Élhossz(p,j) PrSorbanMozgat(j); Ciklus vége Ciklus vége Eljárás vége. Gráfok - fák
Dijkstra algoritmus Dijkstra – legrövidebb utak Alapötlet (pozitív élhosszak esetén): • Az összes pont legyen szürke! • A kezdőpont távolsága önmagától 0, a többi pont távolsága pedig + – becsült felső korlát! • Vegyük a kezdőponthoz legközelebbi szürkét! • Az ő távolsága biztos jó, módosítsuk a belőle kive-zető éleken levő pontok távolságát, ha szükséges! Gráfok - fák
Dijkstra algoritmus LegrövidebbUtak(p): Táv():=(+,…,+); Szín():=(szürke,…,szürke) Honnan(p):=p; Táv(p):=0 Ciklus i=1-től Pontszám-1-ig KiveszMin(p); Szín(p):=fekete Ciklus j=1-től Szomszédpontokszáma(p)-ig k:=Szomszéd(p,j) Ha Szín(k)≠fekete és Táv(k)>Táv(p)+Élhossz(p,k) akkor Táv(k):=Táv(p)+Élhossz(pont,i) Honnan(k):=p; PrSorbanMozgat(k) Ciklus vége Ciklus vége Eljárás vége. Legyenek a pontok egy kupaccal ábrázolt prioritásai sorban! Ekkor KiveszMin=PrSorból, Mozgat=Felfelé. Gráfok - fák
Fák Bináris fa "fordított" ábrázolása, a levelektől vissza: • Ha a bináris fa elemei címezhetőek is (pl. sorszámuk van), akkor elképzelhető egy olyan statikusan láncolt ábrázolás, amikor azt adjuk meg minden elemről, hogy ki van a fában fölötte. Típus BFa=Tömb(1..Max,BFaelem)BFaelem=Rekord(érték: Elemtípus, szülő: 0..Max) Egy ilyen fára persze másféle művele-teket definiálhatunk. Gráfok - fák
Fák Üres(bf): Ciklus i=1-től N-ig bf(i).szülő:=0Ciklus vége Függvény vége. Beilleszt(bf,a,b): {a szülője b-nek} bf(b).szülő:=a Függvény vége. Gráfok - fák
Fák Ősszülő(bf,e): Ha bf(e).szülő=0 akkor Ősszülő:=e különben Ősszülő:=Ősszülő(bf,bf(e).szülő) Függvény vége. Őse?(bf,utód,ős): Ha utód=ős akkor Őse?:=igaz különben ha bf(utód).szülő=0 akkor Őse?:=hamis különben Őse?:=Őse?(bf,bf(utód).szülő,ős) Függvény vége. Megjegyzés: egyetlen fa esetén a bf tömb lehet globális változó is. Gráfok - fák
Fák Ősszülő(bf,e): Ciklus amíg bf(e).szülő≠0 e:=bf(e).szülőCiklus vége Függvény vége. Őse?(bf,utód,ős): Ciklus amíg utód≠ős és bf(utód).szülő≠0 utód:=bf(utód).szülőCiklus végeŐse?:=utód=ős Függvény vége. Ugyanez ciklussal. Gráfok - fák
Minimális költségű feszítőfa Feszítőfa: Egy irányítatlan gráf azon részgráfja, amely fa (kör-mentes, összefüggő) és maximális (tartalmazza a gráf összes pontját). Minimális költségű feszítőfa: Súlyozott gráf azon feszítőfá-ja, amely éleinek összköltsége minimális. Megjegyzés: A szélességi és a mélységi bejárás is egy-egy feszí-tőfát határoz meg, de nem feltétlenül – sőt általában nem – minimális költségűt. Ha a gráf nem összefüggő, akkor feszítő erdőről beszélhetünk. Gráfok - fák
Minimális költségű feszítőfaKruskal algoritmus Ötlet: • a feszítőfa kezdetben álljon Pontszám darab feszítő erdőből (mindegyikben 1-1 pont lesz); • vegyük az éleket hosszuk szerint növekvő sorrendben; • ha egy él a feszítő erdő két különböző feszítőfáját köti össze, akkor biztosan eleme a feszítőfának (mert nincs nála rövidebb, ami a két fát összeköti); • az ilyen fákat egyesítsük és vegyük fel az élt a feszítőfa élei közé! Legyen Fa(i) az i pontot tartalmazó feszítőfa azonosítója! Műveletigény: rendezési idő+ O((Élszám+Pontszám)*log2(Pontszám)) Gráfok - fák
Minimális költségű feszítőfaKruskal algoritmus MinimálisFeszítőfa(F): Üres(F) Ciklus i=1-től PontSzám-ig szülő(i):=i Ciklus vége ÉlekRendezéseHosszSzerint(G) Ciklus e=1-től ÉlSzám-ig i:=Él(e,1); j:=Él(e,2) Ha Fa(i)≠Fa(j) akkor F:=F(i,j); Egyesít(i,j) Ciklus vége Eljárás vége. A Fa(i) gyakori művelet, annyiszor hasz-náljuk, ahány éle van a gráfnak, az Egye-sít pedig ritkább, annyiszor használjuk, ahány pontunk van, azaz az előbbinek kell nagyon hatékonynak lenni. Gráfok - fák
Diszjunkt halmazfelbontás Építsünk egy erdőt, amelyben azonos fában vannak az azonos részhalmazban levő elemek: Egyesít(1,4) hatása: Egyesít(3,4) hatása lehetne: Mi lehetne Egyesít(3,5)? Gráfok - fák
Diszjunkt halmazfelbontás A megoldás: egyesítéskor mindkét fában menjünk a legfelső elemhez és ott hajtsuk végre az egyesítést! Egyesít(3,5) hatása: Gráfok - fák
Diszjunkt halmazfelbontás Egyesít(u,v): Ciklus amíg u≠szülő(u) u:=szülő(u) Ciklus vége Ciklus amíg v≠szülő(v) v:=szülő(v) Ciklus vége Fa(u): szülő(v):=u Ciklus amíg u≠szülő(u) Eljárás vége. u:=szülő(u) Ciklus vége Fa:=u Függvény vége. Gráfok - fák
Diszjunkt halmazfelbontás Amikor a fában felfelé megyünk, akkor még érdemes a megtett utat tömöríteni, azaz minden bejárt pontot a gyökérhez csatolni: Fa(u): v:=u Ciklus amíg v≠szülő(v) v:=szülő(v) Ciklus vége Ciklus amíg u≠szülő(u) w:=szülő(u); szülő(u):=v; u:=w Ciklus vége Fa:=u Függvény vége. Ilyenkor az egyesítés is egyszerűbb lehet, nem kell hozzá ciklus! Gráfok - fák
Diszjunkt halmazfelbontás Ugyanez az úttömörítés rekurzívan: Fa(u): Ha u≠szülő(u) akkor F:=Fa(szülő(u)) szülő(u):=F; Fa:=F különben Fa:=u Függvény vége. Egyesítésként legfeljebb 1 távolságra vagyunk a gyökértől: Egyesít(u,v): Ha u≠szülő(u) akkor u:=szülő(u) Ha v≠szülő(v) akkor v:=szülő(v) szülő(v):=u Eljárás vége. Gráfok - fák
Diszjunkt halmazfelbontás Fa(6) hatása A fa magassága így kisebb lehet, ami gyorsíthatja az algoritmust! Megjegyzés: a két művelet miatt hívják ezt a típust Unió-Holvan típusnak is. Gráfok - fák
Minimális költségű feszítőfaPrim algoritmus Ötlet: • a gráf pontjait 2 halmazba soroljuk, a feszítőfában bent levő és a még azon kívül levő pontok halmazára; • a két halmaz közötti legrövidebb él biztosan eleme a feszí-tőfának (mert a legközelebbi pontba vezet); • vegyük fel az első halmazhoz legközelebbi pontot a feszítőfa pontjai közé és számoljuk újra a szomszédjai távolságát! Tegyük a második halmazbeli pontokat egy prioritásai sorba, az első halmaztól való távolságuk sorrendjében! Műveletigény: O((Élszám+Pontszám)*log2(Pontszám)) Gráfok - fák
Minimális költségű feszítőfaPrim algoritmus MinimálisFeszítőfa(Honnan): Táv(1..PontSzám):=+; PrSorba az összes pont p:=1; Honnan(p):=p; Ciklus i=1-től PontSzám-1-ig PrSorból(p); Táv(p):=0 Ciklus j=1-től SzomszédPontokSzáma(p)-ig s:=SzomszédPont(pt,j) Ha Táv(s)>0 és ÉlHossz(p,s)<Táv(s) akkor Táv(s):=ÉlHossz(p,s) Honnan(s):=p; PrSorbanElőre(s) Ciklus vége Ciklus vége Eljárás vége. Gráfok - fák
Online feszítőfa Ötlet: • kezdetben minden pont külön feszítőfában van; • olvassuk egyesével a gráf éleit; • ha különböző feszítőfabeli pontokat köt össze, akkor egyesítsük a két feszítőfát; • ha azonos feszítőfabeli pontokat köt össze, akkor a köztük levő út leghosszabb élét cseréljük le rá, amennyiben rövidebb nála! Legyen Fa(i) az i pontot tartalmazó feszítőfa azonosítója! Gráfok - fák