V 1.0 Szabó Zsolt, Óbudai Egyetem, Programozás II. Gráfok Dijkstra algoritmus Kruskal algoritmus
V 1.0 Szabó Zsolt, Óbudai Egyetem, Gráfok & Dijkstra algoritmus Gráf: csomópontok és a csomópontokat összekötő élek halmaza Jelenleg: irányítatlan, súlyozott gráf Cél: az 1. csúcsból meghatározni a legrövidebb utat az 5. csúcshoz Dijkstra algoritmus: meghatározza valamely kezdőcsúcsból az összes többi csúcsba vezető legkisebb súlyú utat Mohó algoritmus
V 1.0 Szabó Zsolt, Óbudai Egyetem, Dijkstra algoritmus Tegyük fel, hogy a gráf tárolása és a lényeges műveletek már készen vannak Két tömböt használunk, mindegyik tömb ugyanannyi elemű, mint ahány csúcs van a gráfban Az int típusú ElozoCsucs tömbben tároljuk a kiinduló csúcsból az egyes csúcsokhoz vezető legrövidebb útnál a csúcsot megelőző csúcs sorszámát A double típusú OsszSuly tömbben tároljuk a kiinduló csúcsból az egyes csúcsokhoz vezető jelenleg ismert legrövidebb út összsúlyát Az csúcsokat két halmazra kell osztani: függőben lévő csúcsok és fix útvonalú csúcsok. Mi ezt úgy oldjuk meg, hogy az i. csúcs még függőben van, ha OsszSuly[i]<0 Jelenlegi kezdőcsúcs: #1 !
V 1.0 Szabó Zsolt, Óbudai Egyetem, Inicializálás Kell: kiinduló csúcs (Honnan), innen számoljuk a legrövidebb utat az összes többi csúcshoz Minden I csúcs távolsága legyen az I és a Honnan csúcs távolságának negatív értéke: OsszSuly tömb –(a negatív távolság azt jelzi, hogy a csúcs még nincs kész) –(a Honnan-nal nem szomszédos csúcsoknál ez double.NegativeInfinity) Minden I csúcsra jelezzük, hogy a Honann I útvonalban az I csúcs előtti csúcs a Honnan (közvetlen él): ElozoCsucs tömb –(ez a Honnan csúccsal szomszédos csúcsokra tényleg jó útvonalat definiál, a többi csúcsnál nincs olyan él, szóval ez biztos változni fog) –A Honnan csúcs előtti csúcs legyen -1, ezzel jelezzük, hogy a Honnan a kiinduló-csúcs
V 1.0 Szabó Zsolt, Óbudai Egyetem, Kiinduló állapot IDXElozoCsucsOsszSuly ∞-∞ ∞-∞
V 1.0 Szabó Zsolt, Óbudai Egyetem, Algoritmus Ciklus, amíg van negatív súly (vagyis: amíg létezik nem-kész csúcs) 1.Minimum=az abszolút értékben legkisebb negatív súly sorszáma; 2.OsszSuly[minimum] = -OsszSuly[minimum]; 3.Minden nem-kész (vagyis negatív összsúlyú) csúcsra megnézzük, hogy a jelenlegi OsszSuly[i] súlynál abszolút értékben kisebb súlyt kapunk –e, ha nem az ElozoCsucs[i] eddigi előző csúcson, hanem a Minimum-csúcson keresztül közelítjük meg. Ha igen, akkor ezzel frissítjük az OsszSuly[i]-t, és ElozoCsucs[i]=Minimum; Ciklus vége
V 1.0 Szabó Zsolt, Óbudai Egyetem, iteráció IDXElozoCsucsOsszSuly ∞-∞ ∞-∞ A LEGKISEBB! (Abszolút értékben) 5 -8 -14 -16 4
V 1.0 Szabó Zsolt, Óbudai Egyetem, iteráció A LEGKISEBB! (Abszolút értékben) IDXElozoCsucsOsszSuly 8 -9 2
V 1.0 Szabó Zsolt, Óbudai Egyetem, iteráció IDXElozoCsucsOsszSuly A LEGKISEBB! (Abszolút értékben) -10 9 3
V 1.0 Szabó Zsolt, Óbudai Egyetem, iteráció IDXElozoCsucsOsszSuly A LEGKISEBB! (Abszolút értékben) 10
V 1.0 Szabó Zsolt, Óbudai Egyetem, Végállapot IDXElozoCsucsOsszSuly Bármelyik csúcs elérhető a kezdőcsúcsból indulva Az útvonalak nem feltétlenül alkotnak fát vagy egyenest, ez egyedi
V 1.0 Szabó Zsolt, Óbudai Egyetem, Fejlesztés Gráf osztály: int FPontok; double[,] FSulyok; string[] FCimkek; –public Graf(int n) –public void UjCimke(int n, string cimke) –public void UjEl(int n, int m, double suly) –public int GetPont(string cimke) –public double GetSuly(int n, int m) Dijkstra algoritmushoz szükséges eljárások: –private bool MinKer(double[] d, out int min) Visszaadja, hogy talált –e negatív súlyt, és ha talált, akkor ezek közül melyik az abszolút értékben a legkisebb –public List Utvonal(int honnan, int hova) Itt először legeneráljuk az ElozoCsucs + OsszSuly tömböket, aztán iterálunk, majd legeneráljuk a specifikus utat
V 1.0 Szabó Zsolt, Óbudai Egyetem, Tesztelés (Ctrl+C, Ctrl+V) Graf g; g = new Graf(5); g.UjCimke(0, "#1"); g.UjCimke(1, "#2"); g.UjCimke(2, "#3"); g.UjCimke(3, "#4"); g.UjCimke(4, "#5"); g.UjEl(0, 1, 10); g.UjEl(0, 3, 5); g.UjEl(1, 3, 3); g.UjEl(1, 2, 1); g.UjEl(2, 3, 9); g.UjEl(3, 4, 11); g.UjEl(2, 4, 1); utvonal(g, g.GetPont("#1"), g.GetPont("#5"));
V 1.0 Szabó Zsolt, Óbudai Egyetem, Tesztelés2 (Ctrl+C, Ctrl+V) g = new Graf(20); g.UjCimke(0, "Baja"); g.UjCimke(1, "Budapest"); g.UjCimke(2, "Debrecen"); g.UjCimke(3, "Eger"); g.UjCimke(4, "Esztergom"); g.UjCimke(5, "Győr"); g.UjCimke(6, "Gyula"); g.UjCimke(7, "Kaposvár"); g.UjCimke(8, "Kecskemét"); g.UjCimke(9, "Miskolc"); g.UjCimke(10, "Nyíregyháza"); g.UjCimke(11, "Pécs"); g.UjCimke(12, "Sopron"); g.UjCimke(13, "Szeged"); g.UjCimke(14, "Székesfehérvár"); g.UjCimke(15, "Szolnok"); g.UjCimke(16, "Szombathely"); g.UjCimke(17, "Tatabánya"); g.UjCimke(18, "Veszprém"); g.UjCimke(19, "Zalaegerszeg"); g.UjEl(0, 1, 192.5); g.UjEl(0, 6, 165.7); g.UjEl(0, 13, 93.1); g.UjEl(1, 2, 205.9); g.UjEl(1, 3, 240.3); g.UjEl(1, 8, 81.2); g.UjEl(1, 11, 197.8); g.UjEl(1, 18, 126.4); g.UjEl(2, 3, 35.6); g.UjEl(2, 6, 93.1); g.UjEl(3, 6, 104.3); g.UjEl(4, 7, 152.4); g.UjEl(4, 16, 133.8); g.UjEl(4, 17, 26.1); g.UjEl(5, 12, 33.4); g.UjEl(5, 16, 110.5); g.UjEl(6, 15, 72.3); g.UjEl(7, 11, 65.8); g.UjEl(7, 14, 99.9); g.UjEl(8, 9, 137.5); g.UjEl(8, 13, 91.8); g.UjEl(8, 15, 52.3); g.UjEl(9, 1, 210.4); g.UjEl(9, 6, 141.0); g.UjEl(9, 10, 62.7); g.UjEl(10, 2, 216.8); g.UjEl(10, 15, 44.6); g.UjEl(11, 0, 76.8); g.UjEl(11, 5, 258.2); g.UjEl(11, 14, 116.4); g.UjEl(11, 19, 145.0); g.UjEl(12, 14, 91.5); g.UjEl(12, 17, 60.7); g.UjEl(13, 1, 158.2); g.UjEl(13, 15, 56.3); g.UjEl(14, 1, 62.1); g.UjEl(14, 5, 97.4); g.UjEl(14, 17, 41.7); g.UjEl(15, 1, 109.8); g.UjEl(15, 3, 68.3); g.UjEl(16, 17, 127.5); g.UjEl(16, 19, 78.2); g.UjEl(17, 18, 69.1); g.UjEl(18, 11, 137.6); g.UjEl(18, 14, 46.3); g.UjEl(19, 1, 278.5); g.UjEl(19, 4, 207.2); g.UjEl(19, 6, 377.9); g.UjEl(19, 12, 92.7); utvonal(g, g.GetPont("Szombathely"), g.GetPont("Szeged"));
V 1.0 Tesztelés Szabó Zsolt, Óbudai Egyetem,
V 1.0 Szabó Zsolt, Óbudai Egyetem, Programozás II. Gráfok Dijkstra algoritmus Kruskal algoritmus
V 1.0 Szabó Zsolt, Óbudai Egyetem, Kruskal algoritmus Fa: körmentes (aciklikus), összefüggő gráf Feszítőfa: a gráf összes csúcsát tartalmazó fa, amelynek élei a gráf éleinek részhalmazát alkotják, n csúcs esetén n-1 élből áll Minimális feszítőfa: a feszítőfák közül a legkisebb összsúlyú
V 1.0 Szabó Zsolt, Óbudai Egyetem, "Nem alakul ki kör" ? Útvonalkereséssel (lassabb, talán könnyebben érthető) : Egy listába berakjuk az X csúcsból a feszítőfa meglévő élein keresztül elérhető összes csúcsot (tetszőleges bejárással: szélességi/mélységi). Ha a listában benne van az Y, akkor az X csúcsból a feszítőfa élein keresztül már elérhető az Y, vagyis X és Y egy komponensben van nem adható hozzá a feszítőfához az XY él, mert az kört hozna létre Komponensek használatával (ezt fogjuk implementálni) : Minden csúcshoz komponens-azonosítót rendelünk. Az él nem hoz létre kört, ha külön komponensben lévő csúcsokat köt össze: X és Y csúcs összeköthető éllel, ha a komponens-azonosítójuk különböző. Ezután minden csúcshoz azonos komponens-azonosítót kell rendelni, ami az X vagy az Y csúcs komponensében volt.
V 1.0 Szabó Zsolt, Óbudai Egyetem, Kruskal algoritmus – példa
V 1.0 Szabó Zsolt, Óbudai Egyetem, Kruskal algoritmus – példa
V 1.0 Szabó Zsolt, Óbudai Egyetem, Kruskal algoritmus – példa
V 1.0 Szabó Zsolt, Óbudai Egyetem, Kruskal algoritmus – példa
V 1.0 Szabó Zsolt, Óbudai Egyetem, Kruskal algoritmus – példa
V 1.0 Szabó Zsolt, Óbudai Egyetem, Kruskal algoritmus – példa
V 1.0 Szabó Zsolt, Óbudai Egyetem, Kruskal algoritmus – példa
V 1.0 Szabó Zsolt, Óbudai Egyetem, Kruskal algoritmus – példa
V 1.0 Szabó Zsolt, Óbudai Egyetem, Kruskal algoritmus – megoldási elv 1.Definiáljuk a komponensek tömböt, ahol komponensek[i] az i. csúcs komponens-azonosítóját jelzi. Kezdetben minden tömbelem egyedi [0..X] nincs él a feszítőfában 2.double FSulyok[,] List Elek (GrafEl = {kezdőpont, végpont, súly}) 3.GrafEl rendezése súly szerint növekvő sorrendbe 4.Ciklus, amíg nincs kész a feszítőfa és nem fogynak el az élek a)Akt = sorrendben a következő él, ahol a kezdőpont és a végpont különböző komponensben van b)Ha van ilyen él, akkor az él hozzáadása a feszítőfához c)Ha van ilyen él, akkor az él kezdőpontjának és végpontjának a komponenseit egyesíteni kell 5. public List Kruskal()
V 1.0 Szabó Zsolt, Óbudai Egyetem, Tesztelés (Ctrl+C, Ctrl+V) g = new Graf(8); g.UjCimke(0, "#1"); g.UjCimke(1, "#2"); g.UjCimke(2, "#3"); g.UjCimke(3, "#4"); g.UjCimke(4, "#5"); g.UjCimke(5, "#6"); g.UjCimke(6, "#7"); g.UjCimke(7, "#8"); g.UjEl(g.GetPont("#1"), g.GetPont("#2"), 1); g.UjEl(g.GetPont("#1"), g.GetPont("#6"), 3); g.UjEl(g.GetPont("#2"), g.GetPont("#6"), 4); g.UjEl(g.GetPont("#2"), g.GetPont("#3"), 2); g.UjEl(g.GetPont("#2"), g.GetPont("#7"), 5); g.UjEl(g.GetPont("#6"), g.GetPont("#7"), 8); g.UjEl(g.GetPont("#3"), g.GetPont("#7"), 6); g.UjEl(g.GetPont("#3"), g.GetPont("#4"), 4); g.UjEl(g.GetPont("#4"), g.GetPont("#7"), 7); g.UjEl(g.GetPont("#7"), g.GetPont("#8"), 1); g.UjEl(g.GetPont("#4"), g.GetPont("#8"), 6); g.UjEl(g.GetPont("#4"), g.GetPont("#5"), 7); g.UjEl(g.GetPont("#5"), g.GetPont("#8"), 8); kruskal(g);
V 1.0 Tesztelés Szabó Zsolt, Óbudai Egyetem,
V 1.0 Szabó Zsolt, Óbudai Egyetem, Képek forrásai (megjegyzés: a fenti oldal nagyon jó, de kicsit más a BST, mint az előadáson ismertetett: törlés-C esetnél (amikor mindkét gyermekeleme létezik a törlendő elemnek) nem a bal oldali részfa legjobboldalibb elemét, hanem a jobb oldali részfa legbaloldalibb elemét használja) ml