Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

Gyorsrendezés Elemzések Változatok.

Hasonló előadás


Az előadások a következő témára: "Gyorsrendezés Elemzések Változatok."— Előadás másolata:

1 Gyorsrendezés Elemzések Változatok

2 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.

3 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).

4 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.

5 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.

6 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.

7 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

8 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)

9 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.

10 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)

11 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)

12 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.

13 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.

14 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)

15 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 Minden j  bal, jobb – 1 végezd el: 4 Ha Aj  x akkor 5 i  i Csere(Ai, Aj) vége(ha) vége(minden) 7 Csere(Ai + 1, Ajobb) 8 q  i + 1 Vége(algoritmus)

16 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)

17 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.

18 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).

19 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.

20 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.

21 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.

22 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.  

23 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).

24 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.

25 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.

26 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.

27 Kiegyensúlyozott felosztás
levél

28 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.

29 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.

30 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.

31 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.

32 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

33 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.

34 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.

35 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)


Letölteni ppt "Gyorsrendezés Elemzések Változatok."

Hasonló előadás


Google Hirdetések