Gyorsrendezés Elemzések Változatok.

Slides:



Advertisements
Hasonló előadás
Egy szélsőérték feladat és következményei
Advertisements

Készítette: Kosztyán Zsolt Tibor
Nevezetes algoritmusok
Miskolci Egyetem Informatikai Intézet Általános Informatikai Tanszé k Pance Miklós Adatstruktúrák, algoritmusok előadásvázlat Miskolc, 2004 Technikai közreműködő:
Programozási tételek, és „négyzetes” rendezések
Függvények Egyenlőre csak valós-valós függvényekkel foglalkozunk.
Matematika és Tánc Felkészítő tanár: Komáromi Annamária
HIKGHB Németh Gábor LUF9NV Simon Attila. A programozás alapjai előadás Híradástechnikai Tanszék.
Vektormező szinguláris pontjainak indexe
INFOÉRA Kombinatorikai algoritmusok (Horváth Gyula és Szlávi Péter előadásai felhasználásával) Juhász István-Zsakó László: Informatikai.
Rekurzió (Horváth Gyula és Szlávi Péter előadásai felhasználásával)
Prímtesztelés Témavezető: Kátai Imre Komputeralgebra Tanszék Nagy Gábor:
Copyright, 2009 © Szlávi Péter A kupac és a prioritási sor típuskonstrukciók Szlávi Péter ELTE IK Média- és Oktatásinformatikai Tanszék
4. VÉGES HALMAZOK 4.1 Alaptulajdonságok
Operációkutatás szeptember 18 –október 2.
Az összehasonlító rendezések
Algoritmusok Az algoritmus fogalma:
Gombkötő Attila Lineáris egyenlet.
Készítette: Pető László
Előadó: Prof. Dr. Besenyei Lajos
Mintavételes eljárások
Miskolci Egyetem Informatikai Intézet Általános Informatikai Tanszé k Pance Miklós Adatstruktúrák, algoritmusok előadásvázlat Miskolc, 2004 Technikai közreműködő:
AVL fák.
A digitális számítás elmélete
Számoljuk meg rekurzív függvénnyel egy bináris fa leveleit!
„Országos” feladat. Feladat: Egy tetszőleges, színes országokat tartalmazó térképen akar eljutni egy kommandós csapat egy országból egy másikba. Viszont.
Szélességi bejárás A szélességi bejárással egy irányított vagy irányítás nélküli véges gráfot járhatunk be a kezdőcsúcstól való távolságuk növekvő sorrendjében.
A Fibonacci-féle sorozat
Nevezetes algoritmusok Beszúrás Van egy n-1 elemű rendezett tömbünk. Be akarunk szúrni egy n-edik elemet. Egyik lehetőség, hogy végigszaladunk a tömbön,
Dr. Balogh Péter Gazdaságelemzési és Statisztika Tanszék DE-AMTC-GVK
Előrendezéses edényrendezés – RADIX „vissza”
Utórendezéses edényrendezés – RADIX „előre”
Rendezési algoritmusok
Ismétlés.
Az oszd meg és uralkodj (Divide et Impera) programozási módszer
Rendezések és szövegkezelő függvények
Problémás függvények : lokális optimalizáció nem használható Globális optimalizáció.
Programozási alapismeretek 11. előadás. ELTE Szlávi-Zsakó: Programozási alapismeretek 11.2/ Tartalom  Rendezési.
Algoritmizálás, adatmodellezés tanítása 7. előadás
Mélységi bejárás Az algoritmus elve: Egy kezdőpontból kiindulva addig megyünk egy él mentén, ameddig el nem jutunk egy olyan csúcsba, amelyből már nem.
Algoritmizálás, adatmodellezés tanítása 8. előadás.
Miskolci Egyetem Gazdaságtudományi Kar Üzleti Információgazdálkodási és Módszertani Intézet Mintavételes Eljárások.
Feladatok (értékadás)
Dodekaéder Hamilton köre
Valószínűségszámítás II.
Többdimenziós valószínűségi eloszlások
Bucket sort avagy lineáris idejű rendezés. Pszeudo kód n hosszú L listára for i = 1..n If B[L[i]] != üres Akkor [L[i] Beszúrásos rendezéssel B[L[i]]-be.
Diszjunkt halmazok adatszerkezete A diszjunkt halmaz adatszerkezet diszjunkt dinamikus halmazok S={S 1,…,S n } halmaza. Egy halmazt egy képviselője azonosít.
Programozási alapismeretek 11. előadás
Algoritmusok és adatszerkezetek
(Bináris) Kupac (heap) adattípus
Adatszerkezetek és algoritmusok 2008/ Algoritmus Az algoritmus szó eredete a középkori arab matematikáig nyúlik vissza, egy a i.sz. IX. században.
KÉSZÍTETTE: KOVÁCSICS KRISZTIÁN
Valószínűségszámítás és statisztika előadások
Nevezetes algoritmusok
BFák Kiegyensúlyozott keresőfák
Logikai programozás 6..
Mediánok és rendezett minták
Greedy heurisztikán alapuló közelítő algoritmusok
Halmazműveletek.
Amortizációs elemzés Alapelv: nem egy-egy művelet lefutási idejét vizsgáljuk, hanem több műveletét együtt, sokszor Eredmény: átlagolt időszükséglet időátlagban.
Algoritmusok Az algoritmus fogalma:
Lineáris keresés Keresés (N,A,sorszam) i := 1
Algoritmusok és Adatszerkezetek I.
Adatbázis-kezelés 2. Relációs adatbázisok.
2-3-fák A 2-3-fa egy gyökeres fa az alábbi tulajdonságokkal:
Algoritmusok és Adatszerkezetek I.
Algoritmusok és Adatszerkezetek I.
Állapottér-reprezentáljunk!
Cache példák 2019 (IMSC).
Előadás másolata:

Gyorsrendezés Elemzések Változatok

Bevezetés A gyorsrendezés futási ideje – n elemű bemenő tömbre – legrosszabb esetben Θ(n2). A gyakorlatban sokszor érdemes a gyorsrendezést választani, mivel átlagos futási ideje nagyon jó: Θ(n lg n), és a Θ(n lg n) képlet rejtett állandói meglehetősen kicsik. Egy másik előnye, hogy helyben rendez és virtuálismemória környezetben is jól működik.

Miről lesz szó? Algoritmus, a tömb felosztására. Teljesítménye. A gyorsrendezés változata, amely véletlen mintát használ. Ennek az algoritmusnak jó az átlagos futási ideje, és egyetlen egyedi bemenetre sem éri el a legrosszabb futási időt. A véletlenített változatról megmutatjuk, hogy futási ideje legrosszabb esetben O(n2) átlagosan pedig – különböző elemeket feltételezve – O(n lg n).

A gyorsrendezés leírása A gyorsrendezés az oszd meg és uralkodj elven alapszik. Felosztás: Az A[bal..jobb] tömböt két (esetleg üres) A[bal..q – 1] és A[q +1..jobb] résztömbre osztjuk: az A[bal..q – 1] minden eleme  Aq-nál, ez utóbbi elem viszont  A[q +1..jobb] minden eleménél. Uralkodás: Rendezzük az A[bal..q – 1] és A[q + 1..jobb] résztömböket a gyorsrendezés rekurzív hívásával. Összevonás: Mivel a két résztömböt helyben rendeztük, nincs szükség egyesítésre.

Megoldás Előkészítünk két részsorozatot: az A1, , Aq-1 részsorozat elemei  mint az Aq+1, , xn tömb elemei Valahol közöttük található az Aq > mint az A1, , Aq-1 részsorozat bármely eleme és  mint az Aq+1, , An részsorozat összes eleme. Strázsa (őrszem): az az elem, amely meghatározza a helyet ahol az adott tömb két részre oszlik. Ennek a helynek a meghatározása kulcskérdés az algoritmus végrehajtása során.

A strázsa helye Gyakran: az A1-et választjuk strázsának. Elindulunk a tömb két szélső elemétől és felcseréljük egymás közt azokat az elemeket, amelyek nagyobbak, vagy egyenlők a strázsával (és a tömb első részében találhatók) azokkal, amelyek kisebbek mint a strázsa (és a tömb második részében találhatók). Ahol ez a bejárás véget ér, ott fogjuk két részre osztani a tömböt.

Példa 8, 7, 6, 10, 4, 11, 2, 5, 9 rendezendő sorozat 8, 7, 6, 10, 4, 11, 2, 5, 9 (8 < 9) 8, 7, 6, 10, 4, 11, 2, 5, 9 (8 > 5)  csere 5, 7, 6, 10, 4, 11, 2, 8, 9 (7 < 8) 5, 7, 6, 10, 4, 11, 2, 8, 9 (6 < 8) 5, 7, 6, 10, 4, 11, 2, 8, 9 (10 > 8)  csere 5, 7, 6, 8, 4, 11, 2, 10, 9 (8 > 2)  csere 5, 7, 6, 2, 4, 11, 8, 10, 9 (4 < 8) 5, 7, 6, 2, 4, 11, 8, 10, 9 (11 > 8)  csere 5, 7, 6, 2, 4, 8, 11, 10, 9 8 végleges helyére került

Példa a 8-tól balra eső részsorozatban csak 8-nál kisebb számok találhatók, a 8-tól jobbra eső részsorozatban csak 8-nál nagyobb számok vannak. (5, 7, 6, 2, 4), 8, (11, 10, 9) Ezt a két részsorozatot feldolgozzuk az előbbi módon. A bal részsorozat a következő átalakulásokon megy át: (5, 7, 6, 2, 4)  (4, 7, 6, 2, 5)  (4, 5, 6, 2, 7)  (4, 2, 6, 5, 7)  (4, 2), 5, (6, 7)

Példa (4, 2)  (2, 4), a (6, 7) marad változatlanul. Az eredeti sorozat jobb részsorozata a következő lépések során rendeződik: (11, 10, 9)  (9, 10, 11)  (9, 10), 11 Így az eredeti sorozat most: 2, 4, 5, 6, 7, 8, 9, 10, 11.

Algoritmus QuickSort(bal, jobb): Ha bal < jobb akkor Feloszt(bal, jobb, q) { meghatározzuk azt az q } { helyet, ahol a sorozatot két részsorozatra bontjuk, } { miközben egy elem a végleges q helyére kerül } QuickSort(bal, q-1) QuickSort(q+1, jobb) vége(ha) Vége(algoritmus)

Algoritmus Feloszt(bal, jobb, q): strázsa  Abal i  bal-1 j  jobb+1 Ismételd j  j – 1 { megkeressük azt a j-t amelyre Aj < strázsa } ameddig Aj  strázsa i  i + 1{ megkeressük azt az i-t amelyre Ai > strázsa } ameddig Ai  strázsa Ha i < j akkor { felcseréljük ezt a két elemet } Csere(Ai, Aj) vége(ha) ameddig i  j { kilépünk, amikor i  j } q  j Vége(algoritmus)

Feloszt másképp (fakultatív) Minden lépésben nyilvántartjuk annak a két elemnek az indexét, amelyeket össze kell hasonlítanunk. Minden lépésben megváltozik a két index közül valamelyik aszerint, hogy jobbról haladunk balra, vagy balról jobbra. ii és jj segítségével minden lépésben nyilvántartjuk, hogy melyik index fog nőni és melyik fog csökkenni.

Feloszt másképp Kezdetben az első elemet hasonlítjuk azokkal, amelyek a sorozat végén találhatók jobbról balra haladva. A bal index (i) nem változik, és a jobb index (j) csökken  ii  0, és jj  –1. Az első felcserélés után i nő és j rögzített  ii  1 és jj  0. Az összehasonlításokat addig folytatjuk míg i egyenlővé nem válik j-vel. Amikor i = j, az első elem az i-edik helyre került, amely egyben a végleges hely.

Algoritmus Feloszt_2(bal, jobb, i): i  bal j  jobb ii  0 jj  -1 Amíg i < j végezd el: Ha Ai > Aj akkor Csere(Ai, Aj) id  ii ii  -jj jj  -id vége(ha) i  i + ii j  j + jj vége(amíg) Vége(algoritmus)

Feloszt másképp (3. módszer) Algoritmus Feloszt(bal, jobb, q): { q kimeneti paraméter: a strázsa helye } 1 x  Ajobb 2 i  bal - 1 3 Minden j  bal, jobb – 1 végezd el: 4 Ha Aj  x akkor 5 i  i + 1 6 Csere(Ai, Aj) vége(ha) vége(minden) 7 Csere(Ai + 1, Ajobb) 8 q  i + 1 Vége(algoritmus)

Feloszt másképp (4. módszer) Algoritmus Feloszt(bal, jobb, q): { vagy jobbról indulva a felosztással } x  Abal { őrszem = Abal } i  bal Minden j=bal + 1, jobb végezd el: Ha Aj ≤ x akkor i  i + 1 Csere(Ai, Aj) vége(ha) vége(minden) Csere(Abal, Ai) q  i vége(algoritmus)

A tömb felosztása A következő ábra a Feloszt működését mutatja egy 8 elemű tömbön. Itt a Feloszt mindig kiválasztja az x = Ajobb őrszemet, amely körül az Abal. jobb tömböt felosztja. Az algoritmus a tömböt folyamatosan négy (esetleg üres) tartományra osztja. A Minden ciklus minden iterációjának kezdetén ezek a tömbök bizonyos ciklusinvariánsoknak tekinthető tulajdonságokkal rendelkeznek.

A ciklus minden iterációjának kezdetén a k tömbindexre és az x őrszemre fennáll, hogy 1. Ha bal  k  i, akkor Ak  x (az első „fehér” tartomány). 2. Ha i + 1  k  j – 1, akkor Ak > x (a „szürke” tartomány). 3. Ha k = jobb, akkor Ak = x (az utolsó elem). A j és jobb – 1 közötti indexekre nem vonatkozik a fenti feltételek egyike sem, a nekik megfelelő elemek nincsenek semmilyen kapcsolatban az x őrszemmel (tetszőlegesek).

A ciklusinvariáns Meg kell mutatnunk, hogy ez a ciklusinvariáns igaz az első iteráció előtt, és a ciklus minden iterációja megtartja invariánsnak, majd, hogy az invariáns hasznos tulajdonságnak bizonyul a helyesség bizonyítására, amikor a ciklus befejeződik. Teljesül: A ciklus első iterációja előtt i = bal – 1 és j = bal  egyetlen elem sincs bal és i között, sem pedig i + 1 és j – 1 között  a ciklusinvariáns első két feltétele triviálisan igaz. Az első értékadás (x  Ajobb) miatt a harmadik feltétel is igaz. 1.  Ha bal  k  i, akkor Ak  x. 2.  Ha i + 1  k  j – 1, akkor Ak > x. 3.  Ha k = jobb, akkor Ak = x.

A ciklusinvariáns Megmarad: az összehasonlítás eredményétől függően két esetet kell megkülönböztetnünk. Amikor Aj > x csupán a j értékét kell növelni. Amikor j értéke megnő, a második feltétel Aj –1-re igaz, míg a többi elem változatlan marad. Amikor Aj  x, akkor i nő, Ai és Aj felcserélődik, majd j nő. A csere miatt most Ai  x, és az 1. feltétel teljesül. Hasonlóan, Aj – 1 > x, mivel az az elem, amely az Aj – 1-be került, a ciklusinvariáns miatt nagyobb, mint x. 1.  Ha bal  k  i, akkor Ak  x. 2.  Ha i + 1  k  j – 1, akkor Ak > x. 3.  Ha k = jobb, akkor Ak = x.

A ciklusinvariáns Befejeződik: Befejezéskor j = jobb, ezért a tömb minden eleme az invariáns által leírt valamelyik halmazban van. A tömb elemeit három halmazba tettük: az elsőben x-nél kisebbek vagy vele egyenlők vannak, a másodikban x-nél nagyobbak, és a harmadikban csak az x. A Feloszt két utolsó sora az őrszemet a tömb „közepére” teszi, felcserélve őt a legbaloldalibb, x-nél nagyobb elemmel. A Feloszt eljárás futási ideje egy A[bal..jobb] tömb esetén (n), ahol n = jobb – bal + 1.

A gyorsrendezés hatékonysága A gyorsrendezés futási ideje függ attól, hogy a felosztás kiegyensúlyozott-e vagy sem. A kiegyensúlyozottság függ attól, hogy milyen elemeket választunk a felosztáshoz. Ha a felosztás kiegyensúlyozott, akkor az algoritmus aszimptotikusan olyan gyors, mint az összefésülő rendezés. Ha a felosztás nem kiegyensúlyozott, akkor aszimptotikusan olyan lassú lehet, mint a beszúró rendezés.  

Legrosszabb felosztás A gyorsrendezés legrosszabb esete az, amikor a felosztó eljárás az eredeti tömböt egy n – 1 és egy 0 elemű tömbre osztja. Tételezzük fel, hogy ez a kiegyensúlyozatlan felosztás az algoritmus minden lépésénél (minden rekurzív hívásnál) bekövetkezik. A felosztási idő (n). A rekurzív hívás egy 0 nagyságú tömbre éppen csak visszatér, ezért T(0) = (1). Így a gyorsrendezés futási idejének rekurzív képlete: T(n) = T(n – 1) + T(0) + (n) = T(n – 1) + (n).

Legrosszabb felosztás Intuitív módon, ha összeadjuk a költségeket a rekurzió minden szintjén, akkor egy számtani sorozat összegét kapjuk (n2). Ha alkalmazzuk a helyettesítő módszert, akkor a T(n) = T(n – 1) + (n) rekurziós összefüggés megoldása szintén T(n) = (n2).  Ha a felosztás a rekurzív hívás minden lépésekor maximálisan kiegyensúlyozatlan, akkor a futási idő (n2). A futási idő akkor is (n2), ha a bemeneti tömb már teljesen rendezett ( ebben az esetben a beszúró rendezés futási ideje O(n)), vagy fordított irányban rendezett.

Legjobb felosztás A leggyakoribb felosztásnál a Feloszt eljárás két, n/2 eleműnél nem nagyobb tömböt hoz létre, mivel az egyik n/2, a másik pedig n/2 – 1 elemű. A futási idő rekurzív képlete T(n)  2T(n/2) + (n), amelynek megoldása a mester tétel 2. esete alapján: T(n) = (n lg n). A legjobb felosztás aszimptotikusan gyorsabb algoritmust eredményez.

Kiegyensúlyozott felosztás A gyorsrendezés átlagos futási ideje sokkal közelebb áll a legjobb, mint a legrosszabb futási időhöz. Hogyan jelenik meg a felosztás kiegyensúlyozottsága a futási időt leíró rekurzív képletben? Ha a felosztó eljárás mindig 9:1-hez felosztást ad, (kiegyensúlyozatlan felosztásnak tűnik), a gyorsrendezés futási idejének rekurzív képlete T(n)  T(9n/10) + T(n/10) + cn.

Kiegyensúlyozott felosztás levél

Kiegyensúlyozott felosztás A fa minden szintjének költsége cn, ameddig a log10 n = (lg n) mélységben egy kezdeti feltételt el nem érünk. Az ezután következő szintek költsége legfeljebb cn. A rekurzió a log10/9 n = (lg n) mélységben ér véget. A gyorsrendezés teljes költsége tehát O(n lg n). Ha tehát a felosztás a rekurzív hívás minden szintjén 9:1 arányú (kiegyensúlyozatlannak tűnik), a gyorsrendezés futási ideje O(n lg n) – aszimptotikusan azonos az egyenletes kétfelé osztás esetével.

Az átlagos viselkedés megsejtése A gyorsrendezés viselkedése nem a bemeneti elemektől, hanem azoknak egymáshoz viszonyított helyétől függ. Feltételezés: a bemeneti elemek minden permutációja ugyanolyan eséllyel fordulhat elő. Amikor a gyorsrendezés véletlen bemenetekre fut, nem valószínű, hogy a felosztás minden szinten egyformán történik. Várható, hogy bizonyos felosztások kiegyensúlyozottak lesznek, mások pedig nem.

Az átlagos viselkedés megsejtése Általában a Feloszt eljárás a „jó” és „rossz” felosztások keverékét adja. A Feloszt közepes viselkedése esetében a rekurziós fában a jó és rossz felosztások véletlenszerűen jelennek meg. Tételezzük fel, hogy a rekurziós fában a jó és rossz felosztások váltakozva jelennek meg és, hogy a jó felosztások a legjobb, míg a rossz felosztások a legrosszabb felosztásnak felelnek meg.

Az átlagos viselkedés megsejtése A fa gyökerénél a felosztás költsége n, a keletkezett tömbök pedig n – 1 és 0 eleműek: ez a legrosszabb eset. A következő szintnél az n – 1 méretű tömböt a legjobb esetnek megfelelően egy (n – 1)/2 – 1 és egy (n – 1)/2 méretű résztömbre bontjuk. Tegyük fel, hogy a 0 elemű tömb költsége 1. Egy rossz és utána egy jó felosztás három résztömböt hoz létre, rendre 0, (n – 1)/2 és (n – 1)/2 – 1 elemmel, összesen (n) + (n – 1) költséggel.

Az átlagos viselkedés megsejtése Úgy tűnik tehát, hogy a (n – 1) költségű rossz felosztást elnyelheti egy (n) költségű jó felosztás, és az eredmény jó felosztás. Tehát a gyorsrendezés futási ideje, amikor a jó és rossz felosztások váltakoznak, olyan mintha csak jó felosztások lennének: ugyancsak O(n lg n) idejű, csak nagyobb állandó szerepel az O-jelölésben. Eddig fakultatív

A gyorsrendezés egy véletlenített változata A gyakorlatban nem várhatjuk el, hogy a bemeneti számok minden permutációja ugyanazzal a valószínűséggel jelenjen meg. Feltételezzük, hogy a gyorsrendezés algoritmusa, mielőtt elkezdené a rendezést, véletlenszerűen átrendezi a bemeneti elemeket, hogy ezzel biztosítsa a különböző permutációk azonos valószínűségét. Ez a módosítás nem javít a legrosszabb futási időn, de biztosítja, hogy a futási idő független lesz a bemeneti elemek sorrendjétől.

A gyorsrendezés egy véletlenített változata Egy másik ötlet: őrszemnek az A[bal..jobb] résztömb egy véletlenszerűen választott elemét vesszük. Ez a módosítás biztosítja, hogy az x = Ajobb őrszem ugyanolyan valószínűséggel lehet az A[bal..jobb] résztömb bármelyik eleme. Mivel az őrszemet véletlenszerűen választjuk ki, az átlagos viselkedésben a felosztás várhatóan jól kiegyensúlyozott lesz. A Feloszt és Gyorsrendezés eljárások kevéssé módosulnak: beépítjük két elem cseréjét az új felosztási eljárásba a felosztás előtt.

Algoritmus Véletlen_Feloszt(bal, jobb, q): 1 i  Véletlen(bal, jobb) 2 Csere(Ajobb, Ai) 3 meghívja Feloszt(bal, jobb, q) Vége(algoritmus) Algoritmus Véletlen_Gyorsrendezés(bal, jobb, q): 1 Ha bal < jobb akkor 2 Véletlen_Feloszt(bal, jobb, q) 3 Véletlen_Gyorsrendezés(bal, q-1, q) 4 Véletlen_Gyorsrendezés(q +1, jobb, q) vége(ha)