6. Előadás - Rendező algoritmusok
Rendező algoritmusok
A \(\rho\) (részben) rendezési reláció tulajdonságai:
reflexív: \(a \rho a, \forall a \in A\)
antiszimmetrikus: \(a \rho b\) és \(b \rho a\) esetén \(a = b\)
tranzitív: \(a \rho b\) és \(b \rho c\) esetén \(a \rho c\)
A teljes rendezés esetében elvárjuk azt is, hogy a halmaz bármely két kiválasztott eleme között legyen reláció.
Beszúrásos rendezés
Az algoritmus működése
Kiindulunk egy üres eredmény sorozatból.
Az eredeti tömb elemeit sorban beszúrjuk úgy, hogy mindig rendezett sorozatot kapjunk.
A beszúrás mindig a tömb végétől kezdve történik. (A tömb elejétől kezdve költségesebb lenne.)
\(\rhd\) Egy 9 elemű példán nézzük meg az algoritmus működését!
Párhuzamosítás
Megpróbálhatunk beszúrni úgy elemeket, hogy a korábbi beszúrások még tartanak.
A beszúrást végző iterátorok között megfelelő távolságnak kell lenni.
A beszúrandó elemeket rendezni kell, és a kisebb értékeket kell először beszúrni. (Ez egy független rendezési feladat, melyhez szintén használható például a beszúró rendezés.)
Elvi szinten a megoldás működik, de szinkron működést feltételez.
Szálak szintjén a szinkronizációs költség aránytalanul nagy.
\(\rhd\) Egy 9 elemű példán vizsgáljuk meg 3 iterátorral az algoritmus működését!
\(\rhd\) Rajzoljuk fel a Gantt diagramot az összehasonlítás és csere műveletekkel!
Minimumkiválasztásos rendezés
Az algoritmus működése
Kiindulunk egy üres eredmény sorozatból.
A bemeneti sorozatunknak megkeressük a minimumát.
Ezt beszúrjuk az eredménysorozat végére.
Az előző két lépést addig ismételjük, amíg el nem fogynak az elemek a bemeneti sorozatból.
\(\rhd\) Egy 5 elemű példán nézzük meg az algoritmus működését!
Párhuzamosítás
(I.) A minimum keresést párhuzamosíthatjuk.
Tetszőlegesen sok számítási egység esetében a keresés \(\log_2 (n)\) időre csökkenthető.
A teljes számítási idő így:
Ez ugyan gyorsabb lesz, mint az eredeti \(T(n) = \Theta(n^2)\) időbonyolultság, de nem elég hatékony így sem (a következőkben bemutatásra kerülő algoritmusokhoz képest).
\(\rhd\) Egy 5 elemű példán nézzük meg az algoritmus működését!
\(\rhd\) Rajzoljuk fel a Gantt diagramot az összehasonlításokra nézve, és számítsuk ki a költség, munka, gyorsítás és hatékonyság értékét! (Feltételezzük, hogy tetszőleges sok számítási egységünk lehet!)
(II.) Csoportokat képezhetünk
A négyzetes rendezés analógiájára elképzelhető a következő algoritmus.
Tegyük fel, hogy van \(p\) darab számítási egységünk.
Osszuk fel a rendezendő tömbünket \(p - 1\) részre.
A \(p - 1\) számú számítási egységgel határozzuk meg minden résztömbnek a saját minimumát.
A \(p.\) számítási egységnek allokáljunk egy \(p - 1\) méretű segédtömböt, amelybe belekerülnek a csoportonkénti minimumok.
Kezdjük el kiszámolni a résztömbökben maradt következő minimumot. Közben számítsuk ki a segédtömb minimumát.
A kapott minimumot írjuk az eredménytömb végére.
Amint egy minimumot kivettünk a segédtömbből, írjuk be a helyére a hozzá tartozó csoport következő minimum értékét. (Itt előfordulhat, hogy a \(p.\) számítási egységnek várni kell a minimumérték meghatározására.)
Folytassuk addig az eljárást, amíg minden érték el nem fogy a csoportokból.
A számítás akkor tud hatékony lenni, hogy ha a minimumértékek mindig más csoportokból kerülnek ki. Az algoritmus egyik legrosszabb esete a rendezett tömb.
Összefésülés
Két bemeneti tömbös változat
Egy bemeneti tömbös változat
\(\rhd\) Vizsgáljuk meg az algoritmus működését egy 12 elemű példán!
\(\rhd\) Határozzuk meg az elvégzett összehasonlítások számát!
Batcher-féle páros-páratlan összefésülés
Tegyük fel, hogy adott egy \(A\) és egy \(B\) sorozat, amit össze szeretnénk fésülni.
Bontsuk fel ezeket külön tömbökre az indexek paritása szerint!
Fésüljük össze ezeket az \(U\) és \(V\) sorozatokba:
A \(C\) eredménysorozatot az \(U\) és \(V\) sorozatok összefésülésével kapjuk.
Összefésülő rendezés
\(\rhd\) Egy 10 elemű példán vizsgáljuk meg az algoritmus működését!
\(\rhd\) Feltételezve, hogy a rekurzívan felbontott részek párhuzamosan is végrehajthatók, ábrázolja az előző számításhoz tartozó Gantt diagramot!
Feltételezzük, hogy tetszőleges sok számítási egység rendelkezésünkre áll!
Csak az összehasonlítási műveleteket vegyük figyelembe!
\(\rhd\) Határozzuk meg a költség, munka, gyorsítás és hatékonyság értékeket!
\(\rhd\) Mutassuk meg, hogy kisebb gyorsítással adható hatékonyabb megoldás!
Buborék rendezés
Az alapötlete az, hogy
elegendő a szomszédos elemeket páronként ellenőrízni, hogy a sorozat rendezett-e, és
ha nem megfelelő a pár sorrendje, akkor meg kell cserélni a két elemet.
Az algoritmusnak (szekvenciális esetben is) több változata elképzelhető. A sorozat bejárása történhet
az alacsonyabb indexektől a magasabbak felé, vagy
a magasabbaktól az alacsonyabbak felé.
\(\rhd\) Nézzük meg az algoritmus működését a következő sorozat rendezésével!
Párhuzamosítás
Az algoritmus párhuzamosítása problémás.
A rendezési mód nehezen fogalmazható meg rekurzív formában.
Az elem mozgatása az egész tömbre értendő (tehát a problématér felosztása is körülményes). Ez zárolást tenne szükségessé.
Szinkron rendszert feltételezve indíthatunk párhuzamosan több rendező iterátort.
A közöttük lévő különbségnek legalább 1-nek kell lennie.
Az utolsónak kell tudni megállapítani, hogy a rendezés során történt-e csere.
Egy iterációt követően \(p\)-vel nő a már rendezett elemek száma.
Erősen szinkron működést igényel, hogy az iterátorok ne akadjanak össze.
A gyakori szinkronizáció költsége nagyobb lehet, mint az összehasonlításé és a cseréjé.
\(\rhd\) Vizsgáljuk meg az előbbi példára a párhuzamos változatot!
\(\rhd\) Rajzoljuk fel a Gantt diagramot!
\(\rhd\) Határozzuk meg a költség, munka, gyorsítás és hatékonyság értékeket!
Shell rendezés
\(\rhd\) Rendezzük az
tömböt a \(H = [4, 2, 1]\) növekmények felhasználásával!
Párhuzamosítás
Az azonos távolságokra lévő elemek az egyes iterációkban párhuzamosan rendezhetők.
\(\rhd\) Vizsgáljuk meg az előbbi példára a párhuzamos változatot!
Jelezzük külön az összehasonlítás és a csere műveleteket!
Feltételezzük, hogy a kettő műveleti ideje azonos!
\(\rhd\) Rajzoljuk fel a Gantt diagramot!
\(\rhd\) Határozzuk meg a költség, munka, gyorsítás és hatékonyság értékeket!
Gyorsrendezés
A felosztáshoz használt algoritmus pszeudó kódja:
A gyorsrendezés algoritmusa:
Párhuzamosítás
A felosztást követően a résztömbök függetlenül rendezhetők.
\(\rhd\) Nézzük meg az algoritmus működését a következő sorozat rendezése kapcsán!
\(\rhd\) Számoljuk meg, hogy mennyi kulcsokra vonatkozó összehasonlítás és csere történt!
\(\rhd\) Rajzoljuk fel a Gantt diagramot!
\(\rhd\) Határozzuk meg a költség, munka, gyorsítás és hatékonyság értékeket!
Leszámláló rendezés
A \(k\) felső korlátként megjelölhető az \(A\) sorozat maximális értéke.
Párhuzamosítás
A 4 lépésnek egymás után kell következnie. Párhuzamosításra azokon belül van lehetőség.
Teljesen párhuzamosítható.
A \(C\) segédtömbhöz való hozzáférés miatt ilyen formában zárolásra van szükség.
Prefix számítási problémaként kezelhető.
Szekvenciálisan hajtandó végre.
\(\rhd\) Egy 8 elemű sorozaton vizsgáljuk meg az algoritmus működését!
Kérdések
Adjon példát egy véges (kis elemszámú) halmazon részben rendezésre!
Milyen a beszúrásos rendezés időbonyolultsága?
Milyen a minimumkiválasztásos rendezés időbonyolultsága?
Milyen az összefésülés időbonyolultsága \(n\) és \(m\) méretű bemenetek esetében?
Miért előnyös az összefésülő rendezés esetében a \(q\) érték ilyesfajta megválasztási módja? Működne-e az algoritmus tetszőleges \(q \in [p, r]\) esetében?
Milyen a buborékrendezés időbonyolultsága?
A Shell rendezés esetében mi az elvárás a növekmények sorozatára vonatkozóan?
Mi a legrosszabb esete a gyorsrendezésnek (feltéve, hogy mindig az első elemet választjuk pivót elemnek)?
Egy 32 elemű tömb rendezése esetében mennyi az optimális rekurzív hívási fa magassága?
Feladatok
Beszúró rendezés
Írja fel a beszúró rendezés pszeudó kódját!
Mérje le és ábrázolja a kapott eredményeket a beszúró rendezés időbonyolultságára vonatkozóan!
Vizsgáljuk meg egy 10 elemű minta rendezése esetében, hogy két beszúró iterátor használatával milyen gyorsítás érhető el! (Feltételezzük, hogy a számítások várakoztatás nélkül párhuzamosan futnak!)
Minimumkiválasztásos rendezés
Írja fel a minimumkiválasztásos rendezés pszeudó kódját!
Végezzen méréseket az algoritmus időbonyolultságára vonatkozóan!
Írjon egy rekurzív felbontásra épülő párhuzamos algoritmust a rendezési feladat megoldására!
Hasonlítsa össze azonos bemenetek esetén a szekvenciális és a párhuzamos futási időket!
Összefésülő rendezés
Írja fel annak az algoritmusnak a pszeudó kódját, amelyik párhuzamosan fésüli össze a két bemeneti tömb elejét és végét!
Írja át a
COPY
műveletet egy procedúrára úgy, hogy szerepeljenek benne a másoláshoz használt indexek! (Feltételezzük, hogy az eredmény tömb allokálása automatikusan megtörténik.)Írja fel a 2. és 3.
WHILE
ciklust aCOPY
eljárás meghívásával!Végezzen becsléseket arra vonatkozóan, hogy milyen gyorsítás lenne elérhető, hogy ha a
COPY
műveleteket teljesen párhuzamosítva lehetne végrehajtani! (Ehhez készítsen véletlenszerű bemenetekkel futtatásokat, amelyekkel az eredeti összefésülő algoritmust felhasználva meghatározhatja a konkrét összehasonlítások és értékbeállítások számát!)