Írta: Kurdi Zsombor ALGORITMUSOK OPTIMÁLIS MEGVALÓSÍTÁSA PÁRHUZAMOS KÖRNYEZETBEN PÁRHUZAMOS SZÁMÍTÁSTECHNIKA MODUL PROAKTÍV INFORMATIKAI MODULFEJLESZTÉS Lektorálta: oktatói munkaközösség 1
Írta: Kurdi Zsombor
ALGORITMUSOK OPTIMÁLIS MEGVALÓSÍTÁSA PÁRHUZAMOS KÖRNYEZETBEN
PÁRHUZAMOS SZÁMÍTÁSTECHNIKA MODUL
PROAKTÍV INFORMATIKAI MODULFEJLESZTÉS
Lektorálta: oktatói munkaközösség
1
COPYRIGHT: 2011-2016, Kurdi Zsombor, Óbudai Egyetem, Neumann János Informatikai Kar
LEKTORÁLTA: oktatói munkaközösség
Creative Commons NonCommercial-NoDerivs 3.0 (CC BY-NC-ND 3.0) A szerző nevének feltüntetése mellett nem kereskedelmi céllal szabadon másolható, terjeszthető, megjelentethető és előadható, de nem módosítható.
TÁMOGATÁS: Készült a TÁMOP-4.1.2-08/2/A/KMR-2009-0053 számú, “Proaktív informatikai modulfejlesztés (PRIM1): IT Szolgáltatásmenedzsment modul és Többszálas processzorok és programozásuk modul” című pályázat keretében
KÉSZÜLT: a Typotex Kiadó gondozásában
FELELŐS VEZETŐ: Votisky Zsuzsa
ISBN 978-963-279-559-1
2
http://www.typotex.hu/
KULCSSZAVAK: algoritmus, párhuzamosítás, kölcsönös kizárás, programozási tételek, rendezések, keresések, elosztott adatszerkezetek, Gauss elimináció, Fourier transzformáció, gráfalgoritmusok, tömörítés, titkosítás, mintaillesztés, geometriai algoritmusok ÖSSZEFOGLALÓ: A tananyag leggyakoribb algoritmusok párhuzamosításának kérdésével foglalkozik. Az algoritmusok elemzésével és párhuzamosításával foglalkozó elméleti bevezető után a gyakorlatokra tevődik át a hangsúly. Ez az egyszerűbb algoritmusokkal, a programozási tételekkel – mint például a minimum/maximum keresés, számlálás, összegzés – kezdődik, majd a rendezésiek, keresések, gráfalgoritmusok után olyan bonyolultabb algoritmusok párhuzamosításáról is szó esik, mint a titkosítási, tömörítési és a geometriai problémákat megoldó algoritmusok. Minden esetben az algoritmus bemutatás után foglalkozunk a párhuzamosítás lehetőségével, valamint a soros és párhuzamos implementációval C# nyelven.
Mindezek mellett a tananyagban megtalálható egy rövid fejezet, amely a fontosabb adatszerkezetek elosztott használatával foglalkozik, amely azért fontos, mert a párhuzamos algoritmusok gyakran használhatnak ilyen adatszerkezeteket, amelyeket ilyenkor speciálisan kell kezelnünk (például a kölcsönös kizárás megvalósításával).
3
Tartalomjegyzék • Bevezető • Programozási tételek • Keresések • Mintaillesztések • Rendezések (1) • Rendezések (2) • Mátrixműveletek • Gráfalgoritmusok (1) • Gráfalgoritmusok (2) • Geometria • Tömörítés • Titkosítás
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 4
1. óra Bevezető
Algoritmus fogalma, tulajdonságai Algoritmusok elemzése Aszimptotikus jelölések Példák Algoritmusok párhuzamosítása Módszerek Példák Programok Irodalomjegyzék
© Kurdi Zsombor, ÓE NIK www.tankonyvtar.hu 5
PresenterPresentation NotesA tartalomjegyzékben felsorolt témák nagy részének ismeretét feltételezhetjük a hallgatókról,mert azokat korábbi órákon már tanulták. Ennek az órának a célja az ismeretek felelevenítése,illetve az esetleges hiányosságok pótlása (amennyiben hiányosság mutatkozik valamely hallgatóelőismereteiben, az órán elhangzottakon kívül tanórán kívüli utánajárás is szükséges lehet).
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Hallgatói tájékoztató A jelen bemutatóban található adatok, tudnivalók és információk a
számonkérendő anyag vázlatát képezik. Ismeretük szükséges, de nem elégséges feltétele a sikeres zárthelyinek, illetve vizsgának.
Sikeres zárthelyihez, illetve vizsgához a jelen bemutató tartalmán felül a kötelező irodalomként megjelölt anyag, a gyakorlatokon szóban, illetve a táblán átadott tudnivalók ismerete, valamint a gyakorlatokon megoldott példák és az otthoni feldolgozás céljából kiadott feladatok önálló megoldásának képessége is szükséges.
6
Algoritmus fogalma, tulajdonságai
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 7
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Algoritmus • Algoritmuson olyan módszert (utasítások sorozatát) értünk, amely
valamely problémára megoldást ad. • A fogalom a matematikában jelent meg, de az informatika
népszerűvé válása ültette át a köznyelvbe. • Algoritmust lehet adni
– egy bútordarab összeszerelésére, – egy étel elkészítésére, – otthonunkból az iskolába való eljutásra, – két szám legnagyobb közös osztójának kiszámítására. – …
8
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Algoritmus definíciója • Turing: egy probléma megoldására adott utasítássorozat akkor
tekinthető algoritmusnak, ha van egy vele ekvivalens Turing-gép, amely minden megoldható bemenetre megáll.
• Alternatív definíciók – Regisztergép – Lambda-kalkulus – Rekurzív függvények – Chomsky-nyelvtanok – Markov-algoritmusok
• Mindegyik definíció ekvivalens a Turing-féle meghatározással.
9
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Algoritmusok tulajdonságai • Alaptulajdonságok
– Egy algoritmus egyértelműen leírható véges szöveggel (statikus végesség). – Egy algoritmus minden lépése ténylegesen kivitelezhető. – Egy algoritmus minden időpontban véges sok tárat használ (dinamikus
végesség). – Egy algoritmus véges sok lépésből áll (termináltság).
• Ezek alapján az algoritmus fogalma – Egy algoritmus ugyanarra a bemenetre mindig ugyanazt az eredményt adja
(determináltság). – Minden időpontban egyértelműen adott a következő lépés
(determinisztikusság).
10
Algoritmusok elemzése
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 11
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Algoritmusok elemzése • Befejeződés
– Kiszámíthatóságelméleti feladat.
• Tár- és időigény – Bonyolultságelméleti feladat. – Természetes számokon értelmezett függvények segítségével írható le. – Aszimptotikus korlátokkal adható meg. – A továbbiakban csak ezzel foglalkozunk.
12
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Algoritmusok elemzése • Legyen két függvény f, g: N → Z
– Ha ∃c > 0 és n0, hogy ha n > n0, akkor 0 ≤ f(n) ≤ c⋅g(n), akkor a g függvényt f aszimptotikusan ÉLES felső korlátjának nevezzük (Jele: f(n) = O(g(n) vagy f = O(g))
– Ha ∃c > 0 és n0, hogy ha n > n0, akkor 0 ≤ f(n) < c⋅g(n), akkor a g függvényt f aszimptotikusan NEM ÉLES felső korlátjának nevezzük (Jele: f(n) = o(g(n) vagy f = o(g))
– Ha ∃c > 0 és n0, hogy ha n > n0, akkor 0 ≤ c⋅g(n) ≤ f(n), akkor a g függvényt f aszimptotikusan ÉLES alsó korlátjának nevezzük (Jele: f(n) = Ω(g(n) vagy f = Ω(g))
– Ha ∃c > 0 és n0, hogy ha n > n0, akkor 0 ≤ c⋅g(n) < f(n), akkor a g függvényt f aszimptotikusan NEM ÉLES alsó korlátjának nevezzük (Jele: f(n) = ω(g(n) vagy f = ω(g))
– Ha ∃c1,c2 > 0 és n0, hogy ha n > n0, akkor 0 ≤ c1⋅g(n) ≤ f(n) ≤ c2⋅g(n), akkor a g függvényt f aszimptotikusan éles korlátjának nevezzük (Jele: f(n) = Θ(g(n) vagy f = Θ(g))
13
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Algoritmusok elemzése
14
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Algoritmusok elemzése • A definíciók alapján triviális állítás
– ∀f,g : N → Z függvényre f(n) = Θ(g(n)) ↔ f(n) = O(g(n)) és f(n) = Ω(g(n))
Azaz egy függvény pontosan akkor aszimptotikusan éles korlátja
egy másik függvénynek, ha aszimptotikusan éles alsó és aszimptotikusan éles felső korlátja a függvénynek.
15
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Algoritmusok elemzése • Az O, o, Ω, ω és Θ jelölések mint bináris relációk tulajdonságai
– O, o, Ω, ω és Θ tranzitívak (pl.: f = ω(g) ∧ g = ω(h) → f = ω(h)) – O, Ω és Θ reflexívek (pl. f = Θ(f)) – Θ szimmetrikus (f = Θ(g) ↔ g = Θ(f)) – O és Ω, valamint o és ω „felcserélten szimmetrikusak” (pl.: f = O(g) ↔ g =
Ω(f)) – Rögzített h függvény mellett O(h), o(h), Ω(h), ω(h) és Θ(h) halmazok zártak az
összeadásra és a pozitív számmal való szorzásra (pl.: f = ω(h) ∧ g = ω(h) → f + g = ω(h)) és (pl.: f = ω(h) ∧ c > 0 → c⋅f = ω(h))
– Összegben a nagyobb függvény határozza meg az aszimptotikát: f + g = Θ(max(f, g)) (A max ebben az esetben az aszimptotikusan nagyobb függvényt jelenti.)
16
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Algoritmusok elemzése • Az O, o, Ω, ω és Θ jelölések mint bináris relációk tulajdonságai
(folytatás) – Polinom esetén a legnagyobb fokú tag a meghatározó: aknk + ak-1nk-1 + … + a1n
+ a0 = Θ(n k) – Bármely két (1-nél nagyobb alapszámú) logaritmikus függvény
aszimptotikusan egyenértékű: logan = Θ(logbn). Ezért az alap feltüntetése nem szükséges logan = Θ(logn)
– Hatványfüggvények esetén különböző kitevők különböző függvényosztályokat jelölnek ki: a ≥ 0 és ε > 0 esetén na = O(na+ε) és na ≠ Θ(na+ε), tehát na = o(na+ε)
17
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példa (Összegzés) • Bemenet: n db érték (elemek). • Kimenet: az input értékek összege. • Algoritmus:
s = 0 for i = 1 to n s = s + elemek[i]
• Lépésszám – Legjobb eset: n – Legrosszabb eset: n – Átlagos eset: n – Függvényosztály: Θ(n)
18
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példa (Számlálás) • Bemenet: n db érték (elemek). • Kimenet: az input értékek közül adott tulajdonságú elemek
darabszáma. • Algoritmus:
d = 0 for i = 1 to n if χ(elemek[i]) d = d + 1
• Lépésszám – Legjobb eset: n – Legrosszabb eset: n – Átlagos eset: n – Függvényosztály: Θ(n)
19
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példa (Maximumkeresés) • Bemenet: n db érték (elemek). • Kimenet: az input értékek közül a maximális elem. • Algoritmus:
max = elemek[1] for i = 2 to n if elemek[i] > max max = elemek[i]
• Lépésszám – Legjobb eset: n – Legrosszabb eset: n – Átlagos eset: n – Függvényosztály: Θ(n)
20
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Párhuzamos algoritmusok • A párhuzamos algoritmusok olyan algoritmusok, amelyek a
feladatot több részre osztva, egymással párhuzamosan (több processzoron) egyidejűleg futnak.
• Ezeket az algoritmusokat két nagy csoportba sorolhatjuk – Megosztott algoritmusok Az algoritmust alkotó folyamatok közös memóriát használnak, és azon
keresztül kommunikálnak egymással. – Elosztott algoritmusok Az algoritmushoz tartozó folyamatok teljesen szeparált tárterületen
dolgoznak, majd valamilyen módszerrel összegzik az eredményeket.
21
Algoritmusok párhuzamosítása
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 22
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Algoritmusok párhuzamosítása • „Oszd meg és uralkodj” elv segítségével
– Az adatok felosztása a processzorok (szálak v. folyamatok) között, majd az eredmények összefésülése
Ebben az esetben valamennyi szál elvégzi a teljes algoritmust és az általuk szolgáltatott eredményeket kell valamelyik szálnak összefésülni (ez történhet új algoritmussal vagy a párhuzamosított algoritmus újbóli végrehajtásával).
Olyan algoritmusok esetén hatékony megoldás, amelyek valamennyi inputadatot megvizsgálnak a futás során. (pl. összegzés).
– A feladatok felosztása a processzorok (szálak v. folyamatok) között Ebben az esetben a szálak az algoritmusnak csak egy részét végzik el és az
általuk számolt részeredményt a következő szálnak adják (futószalagszerű rendszer). Az algoritmus végeredményét az utolsó szál szolgáltatja.
Olyan algoritmusok esetén hatékony megoldás, amelyek felbonthatók elemi lépések sorozatára, amelyeket az inputadatokon kell elvégezni, hogy megkapjuk az outputot. (Pl. sin számítás.)
23
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Adatmegosztás
24
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladatmegosztás
25
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példa (Összegzés) • Párhuzamosítás adatmegosztással
– Osszuk k részre az n értéket. – Összegezzük a részeket párhuzamosan. – Összegezzük az egyes részek eredményeit.
• Lépésszám – Legjobb eset: n / k + k – Legrosszabb eset: n / k + k – Átlagos eset: n / k + k – Függvényosztály: Θ(n / k + k)
26
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példa (Számlálás) • Párhuzamosítás adatmegosztással
– Osszuk k részre az n értéket. – Végezzük el a számlálást a részeken párhuzamosan. – Összegezzük az egyes részek eredményeit.
• Lépésszám – Legjobb eset: n / k + k – Legrosszabb eset: n / k + k – Átlagos eset: n / k + k – Függvényosztály: Θ(n / k + k)
27
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példa (Maximumkeresés) • Párhuzamosítás adatmegosztással
– Osszuk k részre az n értéket. – Keressük meg a részek maximumait párhuzamosan. – Keressük meg a maximumot a részeredmények között.
• Lépésszám – Legjobb eset: n / k + k – Legrosszabb eset: n / k + k – Átlagos eset: n / k + k – Függvényosztály: Θ(n / k + k)
28
Programok
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 29
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példaprogramok • A tananyag további részében szereplő példaprogramok
inputadatait a szamok.txt fájl tartalmazza – A fájl első sora a benne található inputadatok darabszámát tartalmazza. – Minden további sor egy-egy inputadatot tartalmaz.
30
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Adatbeolvasás private const string inputFile = "szamok.txt"; private static int[] Beolvas() { StreamReader input = new StreamReader(inputFile); int méret = Convert.ToInt32(input.ReadLine()); int[] számok = new int[méret]; for (int i = 0; i < számok.Length; ++i) számok[i] = Convert.ToInt32(input.ReadLine()); input.Close(); return számok; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
31
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példaprogramok • Minden példaprogram elején az inputfájl tartalmát beolvassuk
egy tömbbe. • Ehhez az input fájl nevét egy konstansban tároljuk. • A beolvasást a Beolvas() nevű művelet végzi. • Az algoritmus futási idejét Stopwatch objektum segítségével
mérjük. • A program végén az eredményt és a futási időt megjelenítjük a
képernyőn.
32
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Program (Soros) private static Stopwatch stopper = new Stopwatch(); static void Main(string[] args) { int[] számok = Beolvas(); stopper.Start(); // algoritmus stopper.Stop(); // eredmény és futási idő kiírás }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
33
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példa (Összegzés) // algoritmus int s = 0; for (int i = 0; i < számok.Length; ++i) s += számok[i]; // eredmény és futási idő kiírás Console.WriteLine("A számok összege: {0}", s); Console.WriteLine("Összesen {0} db számot adtam össze.", számok.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed);
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
34
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példa (Számlálás) // algoritmus int d = 0; for (int i = 0; i < számok.Length; ++i) if (Feltétel(számok[i]) ++d; // eredmény és futási idő kiírás Console.WriteLine("A feltételt teljesítő elemek darabszáma: {0}", d); Console.WriteLine("Összesen {0} db elemet vizsgáltam.", számok.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed); // a Feltétel tetszőleges logikai értékű függvény lehet // most a páros számokat számláljuk private bool Feltétel(int n) { return n % 2 == 0; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
35
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példa (Maximumkeresés) // algoritmus int max = számok[0]; for (int i = 1; i < számok.Length; ++i) if (számok[i] > max) max = számok[i]; // eredmény és futási idő kiírás Console.WriteLine("A legnagyobb szám: {0}", max); Console.WriteLine("Összesen {0} db számot vizsgáltam.", számok.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed);
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
36
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Program (Párhuzamos) private struct SzálParaméter { public int SzálIndex; public int[] Számok; public int StartIndex; public int Hossz; } private static Stopwatch stopper = new Stopwatch(); private static object sync = new object(); private static int[] eredmények = new int[](); private static int lefutottSzálak = 0; static void Main(string[] args) { int[] számok = Beolvas(); stopper.Start(); for (int i = 0; i < szálakSzáma; ++i) { SzálParaméter paraméter; paraméter.SzálIndex = i; Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
37
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Program (Párhuzamos) paraméter.SzálIndex = i; paraméter.Számok = számok; paraméter.Hossz = számok.Length / szálakSzáma; paraméter.StartIndex = paraméter.Hossz * i; ThreadPool.QueueUserWorkItem(new WaitCallback(Szálfüggvény), paraméter); } while (lefutottSzálak < szálakSzáma) Thread.Sleep(1); // összefésülés stopper.Stop(); // eredmény és futási idő kiírás } private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter)obj; // soros algoritmus
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
38
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Program (Párhuzamos) eredmények[param.SzálIndex] = /* az algoritmus eredménye */ lock (sync) { ++lefutottSzálak; } }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
39
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példa (Összegzés) // összefésülés int s = 0; for (int i = 0; i < eredmények.Length; ++i) s += eredmények[i]; // eredmény és futási idő kiírás Console.WriteLine("A számok összege: {0}", s); Console.WriteLine("Összesen {0} db számot adtam össze.", számok.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed);
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
40
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példa (Számlálás) // összefésülés int d = 0; for (int i = 0; i < eredmények.Length; ++i) d += eredmények[i]; // eredmény és futási idő kiírás Console.WriteLine("A feltételt teljesítő elemek darabszáma: {0}", d); Console.WriteLine("Összesen {0} db elemet vizsgáltam.", számok.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed); // a Feltétel tetszőleges logikai értékű függvény lehet // most a páros számokat számláljuk private bool Feltétel(int n) { return n % 2 == 0; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
41
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Példa (Maximumkeresés) // összefésülés int max = eredmények[0]; for (int i = 1; i < eredmények.Length; ++i) if (eredmények[i] > max) max = eredmények [i]; // eredmény és futási idő kiírás Console.WriteLine("A legnagyobb szám: {0}", max); Console.WriteLine("Összesen {0} db számot vizsgáltam.", számok.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed);
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
42
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Házi feladat Próbálja ki a példaprogramokat! Kíséreljen meg javítani a
párhuzamos változatok hatékonyságán!
Megjegyzés – Lehetőség szerint a programokat futtassa egy-, illetve többprocesszoros
gépeken!
43
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Irodalomjegyzék • Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein: Új algoritmusok,
Scolar Kiadó, 2003.
44
www.tankonyvtar.hu
2. óra Programozási tételek
Programozási tételek Összegzés Számlálás Maximumkeresés Másolás Kiválogatás Szétválogatás Metszet Unió Irodalomjegyzék
© Kurdi Zsombor, ÓE NIK 45
PresenterPresentation NotesValamennyi a tartalomjegyzékben felsorolt algoritmus ismeretét feltételezhetjük a hallgatókról,mert azokat korábbi órákon már tanulták, sőt azok implementációját is nagy valószínűséggelelkészítették valamely programozási nyelven. Ennek az órának a célja az ismeretek felelevenítése,illetve az esetleges hiányosságok pótlása (amennyiben hiányosság mutatkozik valamely hallgatóelőismereteiben, az órán elhangzottakon kívül tanórán kívüli utánajárás is szükséges lehet).
www.tankonyvtar.hu
Programozási tételek
© Kurdi Zsombor, ÓE NIK 46
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Programozási tételek • Egy adott feladatosztályba tartozó összes feladatra általános
megoldást adnak. • Csoportosításuk
– Egy sorozathoz egy értéket rendelő feladatok. • Pl.: számítsuk ki n db szám összegét.
– Egy sorozathoz egy sorozatot rendelő feladatok. • Pl.: másoljuk egy sorozat elemeit fordított sorrendben egy másik sorozatba.
– Sorozathoz több sorozatot rendelő feladatok. • Pl.: válogassuk szét egy sorozat páros és páratlan elemeit.
– Több sorozathoz egy sorozatot rendelő feladatok. • Pl.: számítsuk ki két sorozat közös elemeit (metszetét).
47
www.tankonyvtar.hu
Összegzés
© Kurdi Zsombor, ÓE NIK 48
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Összegzés • Feladat
– Számítsuk ki n db szám összegét.
• Sorozathoz értéket rendel.
• Lásd: előző óra.
49
www.tankonyvtar.hu
Számlálás
© Kurdi Zsombor, ÓE NIK 50
Számlálás • Feladat
– Számláljuk meg n db számból hány telesíti F feltételt.
• Sorozathoz értéket rendel. • F feltétel tetszőleges logikai értékű függvény lehet.
• Lásd: előző óra.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 51
www.tankonyvtar.hu
Maximumkeresés
© Kurdi Zsombor, ÓE NIK 52
Maximumkeresés • Feladat
– Keressük meg n db szám közül a legnagyobbat.
• Sorozathoz értéket rendel. • A minimumkeresés is hasonlóan végezhető el. • Megkereshető a sorozat első, illetve utolsó maximuma (ha több
maximum is van). • Feltétellel bővíthető, hogy a sorozat bizonyos (feltételt teljesítő)
elemei közül keressük a maximumot = feltételes maximum keresés.
• Lásd: előző óra.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 53
www.tankonyvtar.hu
Másolás
© Kurdi Zsombor, ÓE NIK 54
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Másolás • Feladat
– Másoljuk át egy sorozat (s) elemeit egy másik sorozatba (t).
• Sorozathoz sorozatot rendel.
• Algoritmus:
for i = 1 to n t[i] = s[i]
55
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Másolás • A másolás közben műveletet is végezhetünk az elemeken.
– Egyszerű művelet (pl. gyökvonás). – Összetett művelet (pl. s[i]-edik Fibonacci-szám kiszámítása).
• Lépésszám
– Legjobb eset: n – Legrosszabb eset: n – Átlagos eset: n – Függvényosztály: Θ(n)
56
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat Adott egy n számot tartalmazó tömb. Számolja ki a számok
négyzetét egy új tömbbe/listába! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
57
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Soros) // a másolat int másolat = new int[számok.Length]; // másolás for (int i = 0; i < számok.Length; ++i) másolat[i] = számok[i] * számok[i]; // eredmény és futási idő kiírás for (int i = 0; i < számok.Length; ++i) Console.WriteLine("{0}^2 = {1}", számok[i], másolat[i]); Console.WriteLine("Összesen {0} db szám négyzetét számoltam ki.", számok.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed);
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
58
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Párhuzamos) // a szál-paraméterek szerkezete struct SzálParaméter { public int[] Számok; // a beolvasott számok public int SzálIndex; // most nincs jelentősége public int StartIndex; // ahonnan elkezdi a szál olvasni a Számok tömböt public int Hossz; // ahány elemet a szálnak fel kell dolgozni } // szálfüggvény private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter )obj; for (int i = param.StartIndex; i < param.StartIndex + param.Hossz; ++i) Eredmény[i] = param.Számok[i] * param.Számok[i]; // a másolás az Eredmény tömbbe // szinkronizációra nincs szükség, mert a szálak a tömb diszjunkt részeit módosítják lock (sync) // a terminálás jelzésére a lefutottSzálak változót használjuk { // itt szükséges a szinkronizáció, mert minden szál módosítja ezt a
változót ++lefutottSzálak; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
59
www.tankonyvtar.hu
Kiválogatás
© Kurdi Zsombor, ÓE NIK 60
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Kiválogatás • Feladat
– Válogassuk ki egy sorozat elemeit, amelyek teljesítik az F feltételt.
• Sorozathoz sorozatot rendel.
• Algoritmus: j = 0 for i = 1 to n if F(s[i]) t[j] = s[i] j = j + 1
61
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Kiválogatás • F feltétel tetszőleges logikai értékű függvény lehet.
• Lépésszám
– Legjobb eset: n – Legrosszabb eset: n – Átlagos eset: n – Függvényosztály: Θ(n)
62
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat Adott egy n számot tartalmazó tömb. Számolja ki a számok
négyzetét egy új tömbbe/listába! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
63
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Soros) // az eredmény List négyzetszámok = new List(); // kiválogatás for (int i = 0; i < számok.Length; ++i) if (Feltétel(számok[i]) négyzetszámok.Add(számok[i]); // eredmény és futási idő kiírás Console.WriteLine("Négyzetszámok:"); for (int i = 0; i < négyzetszámok.Length; ++i) Console.WriteLine(négyzetszámok[i]); Console.WriteLine("Összesen {0} db számot vizsgáltam.", számok.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed); // a feltétel private static bool Feltétel(int n) { return Math.Round(Math.Sqrt(n)) * Math.Round(Math.Sqrt(n)) == n; } Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
64
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Párhuzamos) // a szál-paraméterek szerkezete struct SzálParaméter { public int[] Számok; // a beolvasott számok public int SzálIndex; // most nincs jelentősége public int StartIndex; // ahonnan elkezdi a szál olvasni a Számok tömböt public int Hossz; // ahány elemet a szálnak fel kell dolgozni } // szálfüggvény private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter )obj; for (int i = param.StartIndex; i < param.StartIndex + param.Hossz; ++i) if (Feltétel(param.Számok[i])) // most szükséges a szinkronizáció, mert az Eredmény lock (Eredmény) // lista kezelése nem diszjunkt részekben
történik Eredmény.Add(param.Számok[i]); lock (sync) // a terminálás jelzésére a lefutottSzálak változót használjuk ++lefutottSzálak; // itt szükséges a szinkronizáció, mert minden szál módosítja ezt a
// változót
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
65
www.tankonyvtar.hu
Szétválogatás
© Kurdi Zsombor, ÓE NIK 66
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Szétválogatás • Feladat
– Válogassuk szét egy sorozat F feltételt teljesítő és nem teljesítő elemeit egy-egy sorozatba.
• Sorozathoz több sorozatot rendel.
• Algoritmus:
j1 = 0, j2 = 0 for i = 1 to n if F(s[i]) t1[j1] = s[i] j1 = j1 + 1 else t2[j2] = s[i] j2 = j2 + 1
67
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Szétválogatás • F feltétel tetszőleges logikai értékű függvény lehet.
• Lépésszám
– Legjobb eset: n – Legrosszabb eset: n – Átlagos eset: n – Függvényosztály: Θ(n)
68
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat Adott egy n számot tartalmazó tömb. Válogassuk szét a páros és
páratlan elemeket két új tömbbe/listába! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
69
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Soros) // az eredmény List páros = new List(); List páratlan = new List(); // szétválogatás for (int i = 0; i < számok.Length; ++i) if (Feltétel(számok[i]) páros.Add(számok[i]); else páratlan.Add(számok[i]); // eredmény és futási idő kiírás Console.WriteLine("Páros számok:"); for (int i = 0; i < páros.Length; ++i) Console.WriteLine(páros[i]); Console.WriteLine("Páratlan számok:"); for (int i = 0; i < páratlan.Length; ++i) Console.WriteLine(páratlan[i]); Console.WriteLine("Összesen {0} db számot vizsgáltam.", számok.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed); // a feltétel private static bool Feltétel(int n) { return n % 2 == 0; } Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
70
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Párhuzamos) // a szál-paraméterek szerkezete struct SzálParaméter { public int[] Számok; // a beolvasott számok public int SzálIndex; // most nincs jelentősége public int StartIndex; // ahonnan elkezdi a szál olvasni a Számok tömböt public int Hossz; // ahány elemet a szálnak fel kell dolgozni } // szálfüggvény private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter)obj; for (int i = param.StartIndex; i < param.StartIndex + param.Hossz; ++i) if (Feltétel(param.Számok[i])) // most szükséges a szinkronizáció, mert az Eredmény lock (Páros) // lista kezelése nem diszjunkt részekben történik Páros.Add(param.Számok[i]); else lock (Páratlan) Páratlan.Add(param.Számok[i]); lock (sync) // a terminálás jelzésére a lefutottSzálak változót használjuk ++lefutottSzálak; // itt szükséges a szinkronizáció, mert minden szál módosítja ezt a
// változót } Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
71
www.tankonyvtar.hu
Metszet
© Kurdi Zsombor, ÓE NIK 72
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Metszet • Feladat
– Másoljuk át két (vagy több) sorozat közös elemeit egy új sorozatba.
• Több sorozathoz egy sorozatot rendel.
• Algoritmus
for s in H1 if s not in H2 M = M U {s}
73
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Metszet • A másolás közben tetszőleges műveletet elvégezhetünk az
elemeken.
• Lépésszám – Legjobb eset: min{n,m} – Legrosszabb eset: n*m – Átlagos eset: ~n*m – Függvényosztály: Θ(n*m)
74
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat Adott egy n és egy m számot tartalmazó tömb. Másolja át a két
tömb közös elemeit egy új tömbbe/listába! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
75
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Soros) // az eredmény List metszet = new List(); // metszet for (int i = 0; i < számok1.Length; ++i) { bool tartalmaz = false; for (int j = 0; j < számok2.Length && !tartalmaz; ++j) tartalmaz = számok1[i] == számok2[j]; if (tartalmaz) metszet.Add(számok1[i]); } // eredmény és futási idő kiírás Console.WriteLine("Metszet:"); for (int i = 0; i < metszet.Length; ++i) Console.WriteLine(metszet[i]); Console.WriteLine("Az 1. sorozat elemszáma: {0}", számok1.Length); Console.WriteLine("A 2. sorozat elemszáma: {0}", számok2.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed);
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
76
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Párhuzamos) // a szál-paraméterek szerkezete struct SzálParaméter { public int[] Számok1; // az egyik számsorozat public int[] Számok2; // a másik számsorozat public int SzálIndex; // most nincs jelentősége public int StartIndex; // ahonnan elkezdi a szál olvasni a Számok tömböt public int Hossz; // ahány elemet a szálnak fel kell dolgozni } // szálfüggvény private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter)obj; for (int i = param.StartIndex; i < param.StartIndex + param.Hossz; ++i) { bool tartalmaz = false; for (int j = 0; j < param.Számok2.Length && !tartalmaz; ++j) tartalmaz = param.Számok1[i] == param.Számok2[j]; if (tartalmaz) // most szükséges a szinkronizáció, mert az Eredmény lock (Eredmény) // lista kezelése nem diszjunkt részekben történik Eredmény.Add(param.Számok1[i]); } lock (sync) // a terminálás jelzésére a lefutottSzálak változót használjuk ++lefutottSzálak; // itt szükséges a szinkronizáció, mert minden szál módosítja ezt a változót }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
77
www.tankonyvtar.hu
Unió
© Kurdi Zsombor, ÓE NIK 78
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Unió • Feladat
– Másoljuk át két (vagy több) sorozat elemeit egy új sorozatba úgy, hogy a közös elemek csak egyszer szerepeljenek.
• Több sorozathoz egy sorozatot rendel.
• Algoritmus
E = H1 for s in H2 if s not in E E = E U {s}
79
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Unió • A másolás közben tetszőleges műveletet elvégezhetünk az
elemeken.
• Lépésszám – Legjobb eset: ~n+m – Legrosszabb eset: n*m – Átlagos eset: n*m – Függvényosztály: Θ(n*m)
80
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat Adott egy n és egy m számot tartalmazó tömb. Másolja át a két
tömb elemeit egy új tömbbe/listába úgy, hogy a közös elemek csak egyszer szerepeljenek! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
81
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Soros) // az eredmény List unió = new List(); // unió for (int i = 0; i < számok1.Length; ++i) unió.Add(számok1[i]); for (int i = 0; i < számok2.Length; ++i) { bool tartalmaz = false; for (int j = 0; j < számok1.Length && !tartalmaz; ++j) tartalmaz = számok2[i] == számok1[j]; if (!tartalmaz) unió.Add(számok2[i]); } // eredmény és futási idő kiírás Console.WriteLine("Unió:"); for (int i = 0; i < metszet.Length; ++i) Console.WriteLine(metszet[i]); Console.WriteLine("Az 1. sorozat elemszáma: {0}", számok1.Length); Console.WriteLine("A 2. sorozat elemszáma: {0}", számok2.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed);
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
82
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Párhuzamos) // a szál-paraméterek szerkezete struct SzálParaméter { public int[] Számok1; // az egyik számsorozat public int[] Számok2; // a másik számsorozat public int SzálIndex; // most nincs jelentősége public int StartIndex; // ahonnan elkezdi a szál olvasni a Számok tömböt public int Hossz; // ahány elemet a szálnak fel kell dolgozni } // szálfüggvény (a Számok2 tömb elemeit a fő szálban másoljuk az Eredménybe) private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter)obj; for (int i = param.StartIndex; i < param.StartIndex + param.Hossz; ++i) { bool tartalmaz = false; for (int j = 0; j < param.Számok1.Length && !tartalmaz; ++j) tartalmaz = param.Számok2[i] == param.Számok1[j]; if (!tartalmaz) // most szükséges a szinkronizáció, mert az Eredmény lock (Eredmény) // lista kezelése nem diszjunkt részekben történik Eredmény.Add(param.Számok1[i]); } lock (sync) // a terminálás jelzésére a lefutottSzálak változót használjuk ++lefutottSzálak; // itt szükséges a szinkronizáció, mert minden szál módosítja ezt a változót }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
83
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Házi feladat Próbálja ki a példaprogramokat! Kíséreljen meg javítani a
párhuzamos változatok hatékonyságán!
Megjegyzés – Lehetőség szerint a programokat futtassa egy-, illetve többprocesszoros
gépeken!
84
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Irodalomjegyzék • Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein: Új algoritmusok, Scolar
Kiadó, 2003.
85
www.tankonyvtar.hu
3. óra Keresések
Keresések Lineáris keresés Bináris keresés Visszalépéses keresés Irodalomjegyzék
© Kurdi Zsombor, ÓE NIK 86
PresenterPresentation NotesValamennyi a tartalomjegyzékben fersorolt algoritmus ismeretét feltételezhetjük a hallgatókról,mert azokat korábbi órákon már tanulták, sőt azok implementációját is nagy valószínűséggelelkészítették valamely programozási nyelven. Ennek az órának a célja az ismeretek felelevenítése,illetve az esetleges hiányosságok pótlása (amennyiben hiányosság mutatkozik valamely hallgatóelősimereteiben, az órán elhangzottakon kívül tanórán kívüli utánajárás is szükséges lehet).
www.tankonyvtar.hu
Keresések
© Kurdi Zsombor, ÓE NIK 87
www.tankonyvtar.hu
Lineáris keresés
© Kurdi Zsombor, ÓE NIK 88
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Lineáris keresés • Feladat
– Keressük meg egy sorozat első F feltételt teljesítő elemét (vagy annak indexét).
• Sorozathoz értéket rendel.
• Algoritmus for i = 1 to n if (F(s[i])) break
89
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Lineáris keresés • F feltétel tetszőleges logikai értékű függvény lehet.
• Lépésszám
– Legjobb eset: 1 – Legrosszabb eset: n – Átlagos eset: n/2 – Függvényosztály: Θ(n)
90
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat Adott egy n számot tartalmazó tömb. Keresse meg az első 2-vel, 3-
mal, 5-tel és 7-tel is osztható számot! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
91
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Soros) // keresés bool találat = false; int szám = 0; for (int i = 0; i < számok.Length && !találat; ++i) { if (Feltétel(számok[i])) { találat = true; szám = számok[i]; } } // eredmény és futási idő kiírás if (találat) Console.WriteLine("A feltételnek megfelelő szám: {0}", szám); else Console.WriteLine("Nincs a feltételnek megfelelő szám."); Console.WriteLine("Összesen {0} db számot vizsgáltam.", számok.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed); // feltétel private static bool Feltétel(int n) { return n % 2 == 0 && n % 3 == 0 && n % 5 == 0 && n % 7 == 0; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
92
Lineáris keresés párhuzamosítása • Az eredmények tömbben a szálak futási állapotát is tároljuk. Ha
egy érték. – –2 : még fut a szál. – – 1 : a szál lefutott, de nem talált a feltételnek megfelelő elemet. – Más érték: a szál lefutott és az érték a feltételnek megfelelő elem.
• A program akkor ér véget, amint a legkisebb indexű szál talált
eredményt (vagy egyik szál sem talált megfelelő elemet).
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 93
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Párhuzamos) // inicializálás for (int i = 0; i < szálakSzáma; ++i) eredmények[i] = -2; … // lefutás ellenőrzés int index = 0; while (index < szálakSzáma && eredmények[index] < 0) { if (eredmények[index] == -1) ++index; Thread.Sleep(1); }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
94
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Párhuzamos) // a szál-paraméterek szerkezete struct SzálParaméter { public int[] Számok; // a beolvasott számok public int SzálIndex; // az eredmény tömbben erre az indexre írja a szál a futás eredményét public int StartIndex; // ahonnan elkezdi a szál olvasni a Számok tömböt public int Hossz; // ahány elemet a szálnak fel kell dolgozni } // szálfüggvény private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter)obj; bool találat = false; int szám = 0; for (int i = param.StartIndex; i < param.StartIndex + param.Hossz; ++i) { if (Feltétel(param.Számok[i])) { találat = true; szám = param.Számok[i]; } } if (találat) // szinkronizációra nincs szükség, mert a szálak az eredmény tömb különböző részét módosítják eredmények[param.SzálIndex] = szám; else eredmények[param.SzálIndex] = -1; } Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
95
www.tankonyvtar.hu
Bináris keresés
© Kurdi Zsombor, ÓE NIK 96
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Bináris keresés • Feladat
– Döntsük el, hogy egy rendezett sorozat tartalmazza-e az E elemet.
• Sorozathoz értéket rendel.
• Algoritmus
a = 1, f = n, találat = false while a E) f = k – 1 else a = k + 1
97
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Bináris keresés • Lépésszám
– Legjobb eset: 1 – Legrosszabb eset: log2n – Átlagos eset: ~log2n – Függvényosztály: Θ(log2n)
98
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat Adott egy n számot tartalmazó rendezett tömb. Döntse el, hogy
tartalmazza-e a tömb a 384-es számot! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
99
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Soros) // keresés int eleje = 0; int vége = számok.Length; while (eleje < vége) { int közepe = (eleje + vége) / 2; if (számok[közepe] > keresettSzám) vége = közepe - 1; else if (számok[közepe] == keresettSzám) eleje = vége = közepe; else eleje = közepe + 1; } // eredmény és futási idő kiírás if (eleje == vége) Console.WriteLine("A tömb a(z) {0}. indexen tartalmazza a(z) {1} számot.", eleje, keresettSzám); else Console.WriteLine("A tömb nem tartalmazza a(z) {0} számot.", keresettSzám); Console.WriteLine("Összesen {0} db számot vizsgáltam.", számok.Length); Console.WriteLine("Futási idő: {0}", stopper.Elapsed);
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
100
Bináris keresés párhuzamosítása • Az eredmények tömb helyett eleje és vége nevű tömbök
tartalmazzák az egyes részeken végzett bináris keresések indexeit. • A korábbi adatfelosztás helyett új módszert alkalmazunk.
• A program akkor ér véget, amint egy szál megtalálta a keresett elemet, vagy minden szál lefutott.
• Emiatt a keresés eredménye nemdeterminisztikus (de az eldöntéshez nem szükséges determinisztikus eredmény).
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 101
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Adatbelovasás // az adatfelosztási módszernek megfelelő beolvasás private static int[,] Beolvas() { StreamReader input = new StreamReader(inputFile); int méret = Convert.ToInt32(input.ReadLine()); int[,] számok = new int[szálakSzáma, méret / szálakSzáma]; for (int i = 0; i < méret; ++i) számok[i % szálakSzáma, i /szálakSzáma] = Convert.ToInt32(input.ReadLine()); input.Close(); return számok; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
102
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Párhuzamos) // inicializálás for (int i = 0; i < szálakSzáma; ++i) { eleje[i] = 0; vége[i] = számok.GetLength(1) – 1; } … // lefutás ellenőrzés int index = -1; bool vanFutóSzál = true; while (vanFutóSzál && index < 0) { vanFutóSzál = false; for (int i = 0; i < szálakSzáma; ++i) { if (eleje[i] == vége[i]) index = eleje[i] * szálakSzáma + i; else vanFutóSzál = true; } Thread.Sleep(1); } Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
103
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Megoldás (Párhuzamos) // a szál-paraméterek szerkezete struct SzálParaméter { public int[] Számok; // a beolvasott számok public int SzálIndex; // az eredmény tömbben erre az indexre írja a szál a futás
eredményét public int Keresett Szám; // a keresett szám } // szálfüggvény private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter )obj; while (eleje[param.SzálIndex] < vége[param.SzálIndex]) { int közepe = (eleje[param.SzálIndex] + vége[param.SzálIndex]) / 2; if (param.Számok[param.SzálIndex, közepe] > param.KeresettSzám) vége[param.SzálIndex] = közepe - 1; else if (param.Számok[param.SzálIndex, közepe] == param.KeresettSzám) eleje[param.SzálIndex] = vége[param.SzálIndex] = közepe; else eleje[param.SzálIndex] = közepe + 1; } } Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
104
www.tankonyvtar.hu
Visszalépéses keresés
© Kurdi Zsombor, ÓE NIK 105
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Visszalépéses keresés • Feladat
– Egy rendezett N-est (E1, E2, ... EN) keresünk, amely eleget tesz F feltételnek.
• A rendezett N-es minden komponense rögzített értékkészletből
származhat (pl. E1 Є {R11, R12, ... R1k}). • Az Ei komponenseket részeredményeknek nevezzük. • Az egyes értékkészletek számosságát Mi-vel jelöljük. • Az F feltétel olyan logikai értékű függvény, amely esetében
tetszőleges részeredmény esetében megállapítható, hogy az lehet-e (vagy sem) egy jó eredmény része.
106
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Visszalépéses keresés • Bemenet
– N : a részeredmények száma. – Mi : a részeredmények értékkészletének számossága. – Rij : a részeredmények lehetséges értékei (értékkészlet).
• Kimenet (egy megoldást keresünk)
– Van-e teljes megoldás. – Az egyes részeredmények értéke a megoldásban.
• Kimenet (minden megoldást keressük) – Az összes rendezett N-es, amely megoldás.
107
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat Adott egy sakktábla. Helyezzen fel a táblára 8 királynőt úgy, hogy
közülük semelyik kettő se üsse egymást! Találja meg a probléma összes lehetséges megoldását! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
108
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Keresés (Soros) private static void Keresés(int[] királynők, int i, List eredmény) { for (int j = 0; j < királynőkSzáma; ++j) { if (JóÁllás(királynők, i, j)) { királynők[i] = j; if (i < királynőkSzáma – 1) Keresés(királynők, i + 1, eredmény); else eredmény.Add(ToString(királynők)); } } }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
109
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Segédfüggvény: JóÁllás private static bool JóÁllás(int[] királynők, int i, int j) { bool nincsÜtés = true; for (int k = 0; k < i && nincsÜtés; ++k) { if (királynők[k] == j) nincsÜtés = false; if (királynők[k] == j + (i – k)) nincsÜtés = false; if (királynők[k] == j – (i – k)) nincsÜtés = false; } return nincsÜtés; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
110
Párhuzamosítás • A „rekurzió mentén” párhuzamosítunk: a Keresés() függvény
rekurzív hívását külön szálon indítjuk el.
• Minden szál saját másolattal rendelkezik a részeredményről. – Egyszerűbb szinkronizáció. – Nem szükséges az „eddig bejárt út” tárolása a visszalépéshez.
• A szálak lefutásának ellenőrzéséhez számláljuk az elindított és a már lefutott szálakat. – Ha minden szál lefutott (azaz a két számláló azonos értéken áll), akkor kiírjuk
az eredményt.
• Ezzel a fajta párhuzamosítással nincs szükség visszalépésre, mert a
visszalépés után bejárandó úton már egy másik szál dolgozik.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 111
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Keresés (Párhuzamos) private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter)obj; for (int j = 0; j < KirálynőkSzáma; ++j) { if (JóÁllás(param.Királynők, param.OszlopIndex, j)) { param.Királynők[param.OszlopIndex] = j; if (param.OszlopIndex < királynőkSzáma – 1) { SzálParaméter paraméter; paraméter.Királynők = ÁllásMásol(param.Királynők); paraméter.OszlopIndex = param.OszlopIndex + 1; paraméter.Eredmény = param.Eredmény; lock (syncElindított) { ++ elindítottSzálak; } ThreadPool.QueueUserWorkItem(new WaitCallback(Szálfüggvény), paraméter); } Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
112
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Keresés (Párhuzamos) else { lock (param.Eredmény) { param.Eredmény.Add(ToString(param.Királynők)); } } } } lock (syncLefutott) { ++lefutottSzálak; } }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
113
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Házi feladat Próbálja ki a példaprogramokat! Kíséreljen meg javítani a
párhuzamos változatok hatékonyságán! Számítsa ki a párhuzamos algoritmusok lépésszámát!
Megjegyzések – Lehetőség szerint a programokat futtassa egy-, illetve többprocesszoros
gépeken! – A lépésszámot a legjobb, a legrosszabb és az általános esetre is adja meg!
114
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Irodalomjegyzék címsora • Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein: Új algoritmusok, Scolar
Kiadó, 2003.
• Randomized Parallel Algorithms for Backtrack Search and Branch-and-Bound Computation http://rsim.cs.illinois.edu/arch/qual_papers/systems/7.pdf
115
www.tankonyvtar.hu
4. óra Mintaillesztések
Mintaillesztések Brute-Force algoritmus Knuth–Morris–Pratt algoritmus QuickSearch algoritmus Irodalomjegyzék
© Kurdi Zsombor, ÓE NIK 116
PresenterPresentation NotesAz ezen az órán tárgyalt algoritmusok ismeretét nem feltételezzük a hallgatókról.
www.tankonyvtar.hu
Mintaillesztések
© Kurdi Zsombor, ÓE NIK 117
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Mintaillesztés • Feladat
– Adott elemek egy hosszabb (szöveg) és rövidebb (minta) sorozata.
– Döntsük el, hogy a minta megtalálható-e a szövegben, VAGY – keressük meg a minta első előfordulását a szövegben, VAGY – keressük meg a minta összes előfordulását a szövegben.
• Leggyakoribb felhasználás: karaktersorozatok keresése hosszabb
szövegben.
• A példaprogramokban a szoveg.txt fájl tartalmát használjuk szövegként.
118
PresenterPresentation NotesA továbbiakban a mintaillesztés problémáját úgy kezeljük, mintha szövegben keresnék részeket. A példák jellege is ilyen.Természetesen általánosítással az itt bemutatott algoritmusok más típusú objektumokon végzett mintaillesztésre is használhatók.
www.tankonyvtar.hu
Brute-Force algoritmus
© Kurdi Zsombor, ÓE NIK 119
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Brute-Force algoritmus • Illesszük a mintát (k hosszú) a szöveg (n hosszú) minden indexére
és ellenőrizzük, hogy a teljes minta illeszkedik-e ott. • Lépésszám
– Legjobb eset: k – Legrosszabb eset: k * n – Átlagos eset: k * n / 2 – Függvényosztály: Θ(n)
120
PresenterPresentation NotesEz az algoritmus a triviális megoldást implementálja.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Adatbelovasás private static string Beolvas() { StreamReader input = new StreamReader(inputFile); string szöveg = input.ReadToEnd(); input.Close(); return szöveg; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
121
PresenterPresentation NotesA mintaillesztő algoritmusokhoz egy hosszú szöveget tartalmazó fájlt használunk a korábbi számok.txt helyett.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Program static void Main(string [] args) { string szöveg = Beolvas(); bool egyezik = false; int i; for (i = 0; i < szöveg.Length – keresett.Length && !egyezik; ++i) { egyezik = true; for (int j = 0; j < keresett.Length && egyezik; ++j) { egyezik = szöveg[i + j] == keresett[j]; } } // eredmények kiíratása }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
122
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat Készítse el a bemutatott algoritmus párhuzamos
implementációját! Használja a lineáris keresésnél megismert módszereket!
123
PresenterPresentation NotesA párhuzamos implementáció egyszerű módosíása a korábbi párhuzamos lineáris keresésnek.Ha a hallgatók nem boldogulnak az önálló megoldással, módosítsuk közösen azt a példát.(A megoldást lásd: Példaprogramok/Párhuzamos/BruteForce.zip.)
www.tankonyvtar.hu
Knuth–Morris–Pratt algoritmus
© Kurdi Zsombor, ÓE NIK 124
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Knuth–Morris–Pratt algoritmus • Alapötlet
– Amikor az illeszkedés elromlik, akkor nem feltétlenül kell a következő helyen újrailleszteni a mintát.
– Amennyiben a mintában találhatók ismétlődő részek, akkor nagyobb lépés is megtehető az illesztésben.
• A prefix és szuffix szakaszok a minta ismeretében meghatározhatók.
• Már a mintaillesztés kezdete előtt kiszámolható, hogyan kell áthelyezni a mintát, amikor az nem illeszkedik.
125
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Mintaáthelyezések számítása private static int[] KövetkezőSzámol() { int[] következő = new int[keresett.Length]; következő[0] = 0; for (int i = 1, j = 0; i < keresett.Length;) { if (keresett[i] == keresett[j]) { következő[i] = j; ++i; ++j; } else if (j == 0) { következő[i] = 0; ++i; } else j = következő[j]; } return következő; } Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
126
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Program static void Main(string [] args) { string szöveg = Beolvas(); int[] következő = KövetkezőSzámol(); int i, j; for (i = 0, j = 0; i < szöveg.Length && j < keresett.Length;) { if (szöveg[i] == keresett[j]) { ++i; ++j; } else if (j == 0) ++j; else j = következő[j]; } // eredmények kiíratása }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
127
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat Készítse el a bemutatott algoritmus párhuzamos
implementációját! Használja a lineáris keresésnél megismert módszereket!
128
PresenterPresentation NotesA párhuzamos implementáció egyszerű módosíása a korábbi párhuzamos lineáris keresésnek.Ha a hallgatók nem boldogulnak az önálló megoldással, módosítsuk közösen azt a példát.(A megoldást lásd: Példaprogramok/Párhuzamos/KnuthMorrisPratt.zip.)
www.tankonyvtar.hu
QuickSearch algoritmus
© Kurdi Zsombor, ÓE NIK 129
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
QuickSearch algoritmus • Alapötlet
– A Knuth–Morris–Pratt algoritmushoz hasonló ugrásokkal csökkentsük az illesztések számát.
– Amennyiben a minta utáni első helyen olyan elem van, amely nincs a mintában, ez után a jel után folytathatjuk az illesztést.
130
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Ugrások számítása private static Dictionary UgrásSzámol() { Dictionary ugrás = new Dictionary(); for (int i = 0; i < keresett.Length; ++i) { ugrás[keresett[i]] = keresett.Length – i; } return ugrás; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
131
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Program static void Main(string [] args) { string szöveg = Beolvas(); Dictionary ugrás = UgrásSzámol(); int i, j; for (i = 0, j = 0; i < szöveg.Length – keresett.Length && j < keresett.Length;) { if (szöveg[i + j] == keresett[j]) ++j; else if (i == szöveg.Length – keresett.Length – 1) ++i; else i += ugrás.ContainsKey(szöveg[i + keresett.Length]) ? ugrás[szöveg[i + keresett.Length]] : keresett.Length + 1; } // eredmények kiíratása }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
132
Párhuzamosítás • Újfajta megoldás. • Daraboljuk fel a szöveget azon karakterek mentén, amelyek nem
szerepelnek a mintában. • Az így keletkező részszövegekben elegendő illeszteni a mintát. • Ezt párhuzamosan is megtehetjük.
• Ebben az esetben nem szükséges figyelni az átfedéseket az egyes
részek között, mert a minta úgy nem illeszkedhet.
• A módszer hatékonysága tovább javítható, ha csak azokat a részeket vizsgáljuk, amelyek nem rövidebbek a mintánál.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 133
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Adatbeolvasás private static string Beolvas() { StreamReader input = new StreamReader(inputFile); string szöveg = input.ReadToEnd(); input.Close(); int előző = 0; Dictionary részek = new Dictionary(); for (int i = 0; i < szöveg.Length; ++i) { if (!keresett.Contains(szöveg[i])) { if (i > előző + 1) { részek.Add(előző, szöveg.Substring(előző, i – előző)); } előző = i; } } return szöveg; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
134
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Házi feladat Próbálja ki a példaprogramokat! Kíséreljen meg javítani a
párhuzamos változatok hatékonyságán!
Megjegyzés – Lehetőség szerint a programokat futtassa egy-, illetve többprocesszoros
gépeken!
135
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Irodalomjegyzék • Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein: Új algoritmusok, Scolar
Kiadó, 2003.
136
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
5. óra Rendezések (1)
Rendezések Buborékrendezés ShellSort HeapSort Irodalomjegyzék
137
PresenterPresentation NotesValamennyi a tartalomjegyzékben fersorolt algoritmus ismeretét feltételezhetjük a hallgatókról,mert azokat korábbi órákon már tanulták. Valószínűleg ezen algoritmusok ismerete már felületesebb,mint az első órákon bemutatottaké, ezért az ismeretek felelevenítésére, átismétlésére nagyobb hangsúlytkell fektetnünk!
www.tankonyvtar.hu
Rendezések
© Kurdi Zsombor, ÓE NIK 138
www.tankonyvtar.hu
Buborékrendezés
© Kurdi Zsombor, ÓE NIK 139
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Buborékrendezés • Feladat
– Rendezzük egy sorozat elemeit növekvő sorrendbe.
• Sorozathoz sorozatot rendel. • A rendezés megoldható helyben, vagy másolat készíthető a
sorozat elemeiről.
• Lépésszám – Legjobb eset: 0 – Legrosszabb eset: n2
– Átlagos eset: ~n2
– Függvényosztály: O(n2)
140
Buborékrendezés
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 141
PresenterPresentation NotesMagyarázzuk el az ábra segítségével az algoritmus lépéseit!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat Buborékrendező algoritmussal rendezze a szamok.txt fájl
tartalmát növekvő sorrendbe! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
Megjegyzés – A párhuzamos implementáció során célszerű az 1. órán megismert
adatelosztást alkalmazni.
142
PresenterPresentation NotesPróbálkozzanak meg a hallgatók az önálló implementációval.Szükség esetén készítsük el közösen a programokat!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Buborékrendezés (Soros) for (int i = számok.Length; i >= 2; --i) { for (int j = 0; j < i - 1; ++j) { if (számok[j] > számok[j + 1]) { int tmp = számok[j]; számok[j] = számok[j + 1]; számok[j + 1] = tmp; } } }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
143
PresenterPresentation NotesSzükség esetén (a korábbi ábrát felhasználva) magyarázzuk el az implementációt!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Paraméterstruktúra struct SzálParaméter { public int SzálIndex; public int[] Számok; public int StartIndex; public int Hossz; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
144
PresenterPresentation NotesA paraméterstruktúra az adatok elosztását támogatja a szálak között.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Szálfüggvény private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter)obj; for (int i = param.StartIndex + param.Hossz; i >= param.StartIndex + 2; --i) { for (int j = param.StartIndex; j < i - 1; ++j) { if (param.Számok[j] > param.Számok[j + 1]) { int tmp = param.Számok[j]; param.Számok[j] = param.Számok[j + 1]; param.Számok[j + 1] = tmp; } } } lock (sync) { ++lefutottSzálak; } }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
145
PresenterPresentation NotesA szálfüggvény egy-egy adatszelet rendezését végzi el.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Részeredmények összefésülése int[] indexek = new int[szálakSzáma]; for (int i = 0; i < szálakSzáma; ++i) indexek[i] = i * számok.Length / szálakSzáma; int[] eredmény = new int[számok.Length]; for (int i = 0; i < számok.Length; ++i) { int min = -1; for (int j = 0; j < szálakSzáma; ++j) { if (indexek[j] < (j + 1) * számok.Length / szálakSzáma && (min == -1 || számok[indexek[j]] < számok[indexek[min]])) { min = j; } } if (min >= 0) { eredmény[i] = számok[indexek[min]++]; } } Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
146
PresenterPresentation NotesAz össefésülés során ‘szálakSzáma’ db rendezett sorozatot kell összefésülni.
www.tankonyvtar.hu
ShellSort
© Kurdi Zsombor, ÓE NIK 147
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
ShellSort/Shell rendezés • Feladat
– Rendezzük egy sorozat elemeit növekvő sorrendbe.
• Sorozathoz sorozatot rendel. • A rendezés megoldható helyben, vagy másolat készíthető a
sorozat elemeiről. • A buborékrendezés javított változata.
• Lépésszám
– Függvényosztály: O(n * log2n)
148
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat ShellSort algoritmussal rendezze a szamok.txt fájl tartalmát
növekvő sorrendbe! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
Megjegyzés – A párhuzamos implementáció során célszerű az 1. órán megismert
adatelosztást alkalmazni.
149
PresenterPresentation NotesPróbálkozzanak meg a hallgatók az önálló implementációval.Szükség esetén készítsük el közösen a programokat!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Shell rendezés (Soros) int inkremens = 3; while (inkremens > 0) { for (int i = 0; i < számok.Length; ++i) { int j = i; int tmp = számok[i]; while (j >= inkremens && számok[j - inkremens] > tmp) { számok[j] = számok[j - inkremens]; j -= inkremens; } számok[j] = tmp; } if (inkremens / 2 != 0) inkremens /= 2; else if (inkremens == 1) inkremens = 0; else inkremens = 1; } Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
150
PresenterPresentation NotesSzükség esetén a programkód segítségével magyarázzuk el a Shell rendezés algoritmusának lépéseit!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Shell rendezés (Párhuzamos) • Paraméterstruktúra
– Azonos a buborékrendezésnél látottal
• Szálfüggvény
– A buborékrendezésnél látotthoz hasonló
• Összefésülés
– A buborékrendezésnél látotthoz hasonló
151
www.tankonyvtar.hu
HeapSort
© Kurdi Zsombor, ÓE NIK 152
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
HeapSort/Kupac rendezés • Feladat
– Rendezzük egy sorozat elemeit növekvő sorrendbe.
• Sorozathoz sorozatot rendel. • A rendezés megoldható helyben, vagy másolat készíthető a
sorozat elemeiről.
• Lépésszám – Függvényosztály: O(n*logn)
153
PresenterPresentation NotesSzükség esetén ismételjük át a Heap adatszerkezetet, illetve az algoritmus lépéseit!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat HeapSort algoritmussal rendezze a szamok.txt fájl tartalmát
növekvő sorrendbe! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
Megjegyzés – A párhuzamos implementáció során célszerű az 1. órán megismert
adatelosztást alkalmazni.
154
PresenterPresentation NotesPróbálkozzanak meg a hallgatók az önálló implementációval.Szükség esetén készítsük el közösen a programokat!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Heap sort (Soros) private static void Rendezés(int[] t, int start, int end) { int bal = start + (end - start) / 2; int jobb = end; int offset = start; while (bal >= start) { Süllyeszt(t, offset, bal, end); --bal; } while (jobb > start) { int tmp = t[jobb]; t[jobb] = t[start]; t[start] = tmp; --jobb; Süllyeszt(t, offset, start, jobb); } }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
155
PresenterPresentation NotesA rendezés legkézenfekvőbb implementációja egy rekurzív függvény.A következő dián található a ‘Süllyeszt’ művelet!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Heap sort (Soros) private static void Süllyeszt(int[] t, int offset, int start, int end) { int gyökér = start; while ((gyökér - offset) * 2 + 1
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Szálfüggvény private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter)obj; Rendezés(param.Számok, param.StartIndex, param.StartIndex + param.Hossz - 1); lock (sync) { ++lefutottSzálak; } }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
157
PresenterPresentation NotesA paraméter struktúra azonos az előbbi algoritmusnál használttal.
A szálfüggvényben a korábban megismert rekurzív függvényt használjuk (a paraméter által meghatározott részadatokon).
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Összefésülés int[] indexek = new int[szálakSzáma]; for (int i = 0; i < szálakSzáma; ++i) indexek[i] = i * számok.Length / szálakSzáma; int[] eredmény = new int[számok.Length]; for (int i = 0; i < számok.Length; ++i) { int min = -1; for (int j = 0; j < szálakSzáma; ++j) { if (indexek[j] < (j + 1) * számok.Length / szálakSzáma && (min == -1 || számok[indexek[j]] <
számok[indexek[min]])) min = j; } if (min >= 0) { eredmény[i] = számok[indexek[min]++]; } }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
158
PresenterPresentation NotesAz összefésülés során most is ‘szálakSzáma’ db rendezett sorozatot kell öszefésülni.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Házi feladat Próbálja ki a példaprogramokat! Kíséreljen meg javítani a
párhuzamos változatok hatékonyságán!
Megjegyzés – Lehetőség szerint a programokat futtassa egy-, illetve többprocesszoros
gépeken!
159
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Irodalomjegyzék • Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein: Új algoritmusok, Scolar
Kiadó, 2003.
160
6. óra Rendezések (2)
Rendezések MergeSort QuickSort RADIX rendezés Irodalomjegyzék
© Kurdi Zsombor, ÓE NIK www.tankonyvtar.hu 161
PresenterPresentation NotesValamennyi a tartalomjegyzékben fersorolt algoritmus ismeretét feltételezhetjük a hallgatókról,mert azokat korábbi órákon már tanulták. Valószínűleg ezen algoritmusok ismerete már felületesebb,mint az első órákon bemutatottaké, ezért az ismeretek felelevenítésére, átismétlésére nagyobb hangsúlytkell fektetnünk!
Rendezések
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 162
MergeSort
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 163
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
MergeSort/Összefésüléses rendezés • Feladat
– Rendezzük egy sorozat elemeit növekvő sorrendbe.
• Sorozathoz sorozatot rendel . • A rendezés megoldható helyben, vagy másolat készíthető a
sorozat elemeiről.
• Lépésszám – Legjobb eset: 0 – Legrosszabb eset: n*logn
– Átlagos eset: ~n*logn
– Függvényosztály: O(n*logn)
164
PresenterPresentation NotesSzükség esetén ismételjük át az algoritmus lépéseit!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat MergeSort algoritmussal rendezze a szamok.txt fájl tartalmát
növekvő sorrendbe! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
Megjegyzés – A szálak lefutásának ellenőrzéséhez célszerű valamilyen szemafór típust
használni.
165
PresenterPresentation NotesPróbálkozzanak meg a hallgatók az önálló implementációval.Szükség esetén készítsük el közösen a programokat!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
MergeSort (Soros) private static void Rendezés(int[] t, int bal, int jobb) { if (jobb > bal) { int közép = (jobb + bal) / 2; Rendezés(t, bal, közép); Rendezés(t, közép + 1, jobb); Összefésülés(t, bal, közép + 1, jobb); } }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
166
PresenterPresentation NotesAz algoritmus legkézenfekvőbb implementációja egy rekurzív függvény.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
MergeSort (Soros) private static void Összefésülés(int[] t, int bal, int közép, int jobb) { int[] tmptömb = new int[t.Length]; int tmpindex = bal; int balvég = közép - 1; int jobbvég = közép; int elemszám = jobb - bal + 1; while (bal
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
MergeSort (Soros) while (bal
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Paraméterstruktúra struct SzálParaméter { public int[] Számok; public int Bal; public int Jobb; public EventWaitHandle Szemafor; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
169
PresenterPresentation NotesA paraméterstruktúra eltér a korábban látottaktól:–Meghatározza a rendezendő részt.–Tartalmaz egy szemafort, amely segítségével ellenőrizhető, hogy az adott szál befejezte-e a rendezést.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Szálfüggvény private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter)obj; if (param.Jobb > param.Bal) { int közép = (param.Bal + param.Jobb) / 2; SzálParaméter paraméter1; paraméter1.Számok = param.Számok; paraméter1.Bal = param.Bal; paraméter1.Jobb = közép; paraméter1.Szemafor = new ManualResetEvent(); ThreadPool.QueueUserWorkItem(new WaitCallback(Szálfüggvény), paraméter1); SzálParaméter paraméter2; paraméter2.Számok = param.Számok; paraméter2.Bal = közép + 1; paraméter2.Jobb = param.Jobb; paraméter2.Szemafor = new ManualResetEvent();
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
170
PresenterPresentation NotesA szálfüggvényben – a soros implementációhoz hasonlóan – rekurzívan két részre osztjuk a rendezendő részt és azokon végezzükel a rendezést úgy, hogy újabb szálakat indítunk. Amikor az a 2 szál elvégezte a munkáját, akkor az aktuális részadatok rendezettségétaz összefésüléssel biztosítjuk.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Szálfüggvény ThreadPool.QueueUserWorkItem(new WaitCallback (Szálfüggvény), paraméter2); WaitHandle.WaitAll(new WaitHandle [] { paraméter1.Szemafor, paraméter2.Szemafor }); Összefésülés(param.Számok, param.Bal, közép + 1, param.Jobb); } param.Szemafor.Set(); }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
171
PresenterPresentation NotesAz implementáció mellékhatása, hogy nincs szükség összefésülésre.
QuickSort
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 172
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
QuickSort/Gyorsrendezés • Feladat
– Rendezzük egy sorozat elemeit növekvő sorrendbe.
• Sorozathoz sorozatot rendel. • A rendezés megoldható helyben, vagy másolat készíthető a
sorozat elemeiről.
• Lépésszám – Legjobb eset: 0 – Legrosszabb eset: n * logn
– Átlagos eset: ~n * logn
– Függvényosztály: O(n * logn)
173
PresenterPresentation NotesSzükség esetén ismételjük át az algoritmus lépéseit!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat QuickSort algoritmussal rendezze a szamok.txt fájl tartalmát
növekvő sorrendbe! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
Megjegyzés – A párhuzamos implementáció során célszerű a visszalépéses keresésnél
megismert rekurzív szálindítási technikát alkalmazni.
174
PresenterPresentation NotesPróbálkozzanak meg a hallgatók az önálló implementációval.Szükség esetén készítsük el közösen a programokat!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
QuickSort (Soros) private static void Rendezés(int[] t, int bal, int jobb) { int balelem = t[bal]; int balindex = bal; int jobbindex = jobb; while (bal < jobb) { while (bal < jobb && t[jobb] >= balelem) --jobb; if (bal != jobb) { t[bal] = t[jobb]; ++bal; } while (bal < jobb && t[bal]
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
QuickSort (Soros) if (bal != jobb) { t[jobb] = t[bal]; --jobb; } } t[bal] = balelem; if (balindex < bal) Rendezés(t, balindex, bal - 1); if (jobbindex > bal) Rendezés(t, bal + 1, jobbindex); }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
176
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Paraméterstruktúra struct SzálParaméter { public int[] Számok; public int Bal; public int Jobb; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
177
PresenterPresentation NotesA paraméterstruktúra illeszkedik az algoritmus tömbkezeléséhez.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Szálfüggvény private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter)obj; int balelem = param.Számok[param.Bal]; int balindex = param.Bal; int jobbindex = param.Jobb; // Rendezés if (balindex < param.Bal) { SzálParaméter paraméter; paraméter.Számok = param.Számok; paraméter.Bal = balindex; paraméter.Jobb = param.Bal - 1; lock (syncElindított) { ++elindítottSzálak; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
178
PresenterPresentation NotesA szálfüggvény hasonló az előző algoritmus implementációjában használthoz, de itt nincs szükgés összefésülésre, ezértnem szükséges az elindított szálak lefutásának bevárása.
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Szálfüggvény ThreadPool.QueueUserWorkItem(new WaitCallback(Szálfüggvény), paraméter); } if (jobbindex > param.Bal) { SzálParaméter paraméter; paraméter.Számok = param.Számok; paraméter.Bal = param.Bal + 1; paraméter.Jobb = jobbindex; lock (syncElindított) { ++elindítottSzálak; } ThreadPool.QueueUserWorkItem(new WaitCallback(Szálfüggvény), paraméter); } lock (syncLefutott) { ++lefutottSzálak; } }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
179
RADIX rendezés
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK 180
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
RADIX rendezés • Feladat
– Rendezzük egy sorozat elemeit növekvő sorrendbe.
• Sorozathoz sorozatot rendel. • A rendezés megoldható helyben, vagy másolat készíthető a
sorozat elemeiről. • A Vödrös rendezés speciális formája.
– Azonos hosszúságú sorozatok rendezésére használható.
• Lépésszám
– Függvényosztály: Θ(n)
181
PresenterPresentation NotesSzükség esetén ismételjük át az algoritmus lépéseit!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Feladat RADIX/Vödrös rendezés algoritmussal rendezze a szamok.txt fájl
tartalmát növekvő sorrendbe! Oldja meg a feladatot soros és párhuzamos algoritmussal is!
182
PresenterPresentation NotesPróbálkozzanak meg a hallgatók az önálló implementációval.Szükség esetén készítsük el közösen a programokat!
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
RADIX (Soros) for (int i = 0; i < lépésekSzáma; ++i) { for (int j = 0; j < számok.Length; ++j) tárolók[Számjegy(számok[j], i)].Enqueue(számok[j]); int index = 0; for (int j = 0; j < tárolók.Length; ++j) { while (tárolók[j].Count > 0) számok[index++] = tárolók[j].Dequeue(); } }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
183
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Paraméterstruktúra struct SzálParaméter { public int[] Számok; public int StartIndex; public int Hossz; public int Lépés; public int[] Tárolók; }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
184
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Szálfüggvény private static void Szálfüggvény(object obj) { SzálParaméter param = (SzálParaméter)obj; for (int i = param.StartIndex; i < param.StartIndex + param.Hossz; ++i) { lock (param.Tárolók) { ++param.Tárolók[param.Számok[i]]; } } lock (syncLefutott) { ++lefutottSzálak; } }
Program.cs
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23
185
www.tankonyvtar.hu © Kurdi Zsombor, ÓE NIK
Rendezett sorozat előállítása for (int i = 0, index = 0; i < tárolók.Length; ++i) { for (int j = 0; j < tárolók[i]; ++j) számok[index++] = i; }
Program.cs