Összefésülő rendezés (merge sort)

  • Informatika
  • algoritmus elemzés
  • időkomplexitás
  • térkomplexitás
  • oszd meg és uralkodj
  • rendezési algoritmusok
  • programozás oktatás

Podcast

Összefésülő rendezés0:00 / 12:41
0:001:00 remaining

Az összefésülő rendezés (merge sort) az egyik leghatékonyabb, összehasonlításon alapuló rendezési algoritmus, amelyet John von Neumann fejlesztett ki 1945-ben. Célja, hogy elemekből álló listákat vagy tömböket rendezzen növekvő vagy csökkenő sorrendbe. Ez az algoritmus az „oszd meg és uralkodj” paradigmát követi, ami kulcsfontosságú a működésében.

Ez az összefoglaló bemutatja az összefésülő rendezés működését, komplexitását és gyakorlati előnyeit, hogy segítsen megérteni ezt az alapvető algoritmust.

Check what you already know

Test · 20 questions · first 3 free

Question 1 of 30%

Az összefésülő rendezésnél a segédtömb helytelen méretezése általában csak kisebb teljesítménycsökkenést okoz, de nem vezet programhibához vagy memória szivárgáshoz.

Practise it with flashcards

44 cards · first 3 free, no account

1 / 44

Ki fejlesztette ki az összefésülő rendezést és mikor?

John von Neumann fejlesztette ki 1945-ben.

Tap to flip · Swipe to navigate

Mi az összefésülő rendezés (Merge Sort) és hogyan működik?

Az összefésülő rendezés különösen népszerű stabilitása és kiszámítható teljesítménye miatt. Időkomplexitása minden esetben O(n log n), ami azt jelenti, hogy a rendezés sebessége nem függ az adatok kezdeti elrendezésétől. Bár memóriaigénye magasabb lehet, megbízhatósága és hatékonysága miatt széles körben alkalmazzák.

Az „Oszd meg és uralkodj” elv az összefésülő rendezésben

Az „oszd meg és uralkodj” egy általános algoritmikus tervezési technika, amely három fő lépésből áll:

  1. Felosztás (Divide): A rendezendő listát felosztjuk két vagy több, kisebb alproblémára. Az összefésülő rendezés esetében a listát a középpontjánál kettévágjuk két nagyjából egyenlő méretű részre.
  2. Uralkodás (Conquer): Az alproblémákat rekurzívan megoldjuk. Ez addig folytatódik, amíg az alproblémák triviálisan megoldhatóak nem lesznek, például egy egyelemű lista esetében, amely definíció szerint már rendezett.
  3. Összefésülés (Combine): Az alproblémák megoldásait egyesítjük, hogy megkapjuk az eredeti probléma rendezett megoldását. Ez a lépés a kulcsfontosságú: két rendezett al-listát egyetlen rendezett listává fésülünk össze.

Az összefésülő rendezés algoritmusa lépésről lépésre

Az algoritmus két fő fázisra bontható:

1. Felosztási fázis (Rekurzió)

Ez a fázis rekurzívan működik egy adott lista (A), valamint annak kezdő (bal) és záró (jobb) indexe alapján:

  • Alapeset: Ha bal ≥ jobb, azaz a lista egy vagy nulla elemet tartalmaz, akkor az már rendezett, és nincs további teendő.
  • Rekurzív lépés:
  1. Meghatározzuk a lista középső indexét: közép = (bal + jobb) / 2 (egészrész).
  2. Rekurzívan meghívjuk az összefésülő rendezést az első félre: MergeSort(A, bal, közép).
  3. Rekurzívan meghívjuk az összefésülő rendezést a második félre: MergeSort(A, közép+1, jobb).

Ez a felosztási folyamat addig tart, amíg a lista egyelemű al-listákra nem bomlik. Ekkor a rekurzió elkezd visszatérni, és megkezdődik az összefésülési fázis.

2. Összefésülési fázis (Merge)

Ez a fázis felelős két már rendezett al-lista egyetlen rendezett listává történő egyesítéséért. Tegyük fel, hogy van két rendezett al-listánk: BalLista és JobbLista.

  1. Létrehozunk egy ideiglenes segédtömböt, amelynek mérete megegyezik a két összefésülendő lista együttes méretével. Ez a segédtömb fogja tárolni az összefésült eredményt.
  2. Két mutatót (i és j) inicializálunk a BalLista és JobbLista elejére (azaz 0-ra).
  3. Egy harmadik mutatót (k) inicializálunk a segédtömb elejére (0-ra).
  4. Amíg mindkét lista tartalmaz feldolgozandó elemeket (azaz i < BalLista.hossz és j < JobbLista.hossz):
  • Összehasonlítjuk BalLista[i] és JobbLista[j] elemeket.
  • A kisebbik elemet átmásoljuk a segédtömbbe segédtömb[k] pozícióra.
  • Növeljük a másolt elem listájának mutatóját (vagy i-t, vagy j-t) és a segédtömb mutatóját (k-t).
  1. Miután az egyik lista összes elemét feldolgoztuk, a másik listában maradt összes elemet egyszerűen átmásoljuk a segédtömbbe (mivel azok már rendezettek).
  2. Végül a segédtömb tartalmát visszamásoljuk az eredeti tömb megfelelő részébe.

Összefésülő rendezés (Merge Sort) példa

Nézzünk egy példát a [38, 27, 43, 3, 9, 82, 10] számsorozat rendezésére.

Kezdeti lista: [38, 27, 43, 3, 9, 82, 10]

1. Felosztási fázis (rekurziós fa):

  • [38, 27, 43, 3, 9, 82, 10]
  • [38, 27, 43, 3] és [9, 82, 10]
  • [38, 27] és [43, 3] (bal oldal)
  • [38] és [27] (bal-bal)
  • [43] és [3] (bal-jobb)
  • [9, 82] és [10] (jobb oldal)
  • [9] és [82] (jobb-bal)
  • [10] (jobb-jobb)

Most minden al-lista egyelemű, tehát rendezett. A rekurzió visszatér, és megkezdődik az összefésülés.

2. Összefésülési fázis (alulról felfelé):

  • [38] és [27] összefésülése → [27, 38]
  • [43] és [3] összefésülése → [3, 43]
  • [9] és [82] összefésülése → [9, 82]
  • [10] (már rendezett)

Ezek után a következő szinten lévő listákat fésüljük össze:

  • [27, 38] és [3, 43] összefésülése → [3, 27, 38, 43]
  • [9, 82] és [10] összefésülése (helyesen): BalLista = [9, 82], JobbLista = [10]
  • BalLista[0] (9) < JobbLista[0] (10) → segédtömb[0] = 9, i=1, k=1
  • BalLista[1] (82) > JobbLista[0] (10) → segédtömb[1] = 10, j=1, k=2
  • JobbLista kimerült. BalLista maradék: [82]
  • segédtömb[2] = 82, i=2, k=3
  • Eredmény: [9, 10, 82]

Végül a két nagy rendezett lista összefésülése:

  • [3, 27, 38, 43] és [9, 10, 82] összefésülése.
  • Végeredmény: [3, 9, 10, 27, 38, 43, 82]

Komplexitás elemzés: Összefésülő rendezés idő- és térkomplexitása

Az algoritmusok teljesítményét két fő metrikával jellemezzük: időkomplexitással és memóriaigénnyel (térkomplexitással). Az összefésülő rendezés elemzése kulcsfontosságú a hatékonyság megértéséhez.

Időkomplexitás: O(n log n) minden esetben

Az összefésülő rendezés időkomplexitása O(n log n) a legjobb, átlagos és legrosszabb esetben is. Ez az egyik legfontosabb előnye a többi rendezési algoritmushoz képest.

  • Felosztási fázis: A lista felosztása minden lépésben O(1) időt vesz igénybe, de a rekurziós hívások száma határozza meg a teljes időt.
  • Összefésülési fázis: Két rendezett lista összefésülése, amelyek összesen m elemet tartalmaznak, O(m) időt vesz igénybe, mivel minden elemet legfeljebb egyszer kell összehasonlítani és átmásolni.

A rekurziós reláció, amely leírja az időkomplexitást, a következő: T(n) = 2T(n/2) + O(n)

Ez azt jelenti, hogy egy n méretű probléma megoldásához két n/2 méretű alproblémát oldunk meg rekurzívan (ez a 2T(n/2) rész), majd az eredményeket O(n) idő alatt összefésüljük (ez az O(n) rész). A rekurziós fa mélysége log₂n, és minden szinten O(n) munka történik az összefésülések során. Így a teljes időkomplexitás O(n log n).

Összehasonlításképpen, a legegyszerűbb rendezési algoritmusok (pl. buborékrendezés, beszúrásos rendezés) időkomplexitása O(n²), ami sokkal lassabb nagy adathalmazok esetén. Például, ha n = 1 000 000, akkor n² = 1 000 000 000 000, míg n log n ≈ 20 000 000. A különbség óriási.

Memóriaigény (Térkomplexitás): O(n)

Az összefésülő rendezés memóriaigénye O(n). Ez azért van, mert az összefésülési fázis során szükség van egy segédtömböt, amelynek mérete megegyezik az eredeti lista méretével (vagy annak egy részével, de a legrosszabb esetben az egész listát tárolhatja).

Ez a segédtömb ideiglenesen tárolja az összefésült elemeket, mielőtt visszamásolná azokat az eredeti tömbbe. Ez a memóriaigény hátrányt jelenthet korlátozott memóriájú rendszerekben, vagy nagyon nagy adathalmazok esetén, ahol az in-place (helyben végzett) rendezési algoritmusok előnyösebbek lehetnek. Léteznek in-place összefésülő rendezés változatok, amelyek O(1) extra memóriát használnak, de ezek sokkal bonyolultabbak és általában lassabbak, mint a standard O(n) memóriát használó változat.

Összefésülő rendezés (Merge Sort) előnyei és hátrányai

Az összefésülő rendezés kiváló választás sok alkalmazáshoz, de fontos ismerni a korlátait is.

Előnyök:

  • Stabil: Az azonos értékű elemek relatív sorrendje megmarad a rendezés során. Ez fontos lehet bizonyos alkalmazásokban, ahol az elemeknek van másodlagos rendezési kritériuma is.
  • Kiszámítható teljesítmény: Időkomplexitása mindig O(n log n), függetlenül az adatok kezdeti elrendezésétől. Nincs „legrosszabb eset” teljesítményromlás.
  • Párhuzamosítható: Az „oszd meg és uralkodj” jellege miatt könnyen párhuzamosítható, ami modern többmagos processzorokon vagy elosztott rendszerekben előnyös lehet.
  • Külső rendezésre alkalmas: Nagyon nagy adathalmazok rendezésére is alkalmas, amelyek nem férnek el teljesen a memóriában (ekkor fájlokba írja és olvassa az al-listákat).

Hátrányok:

  • Magas memóriaigény: Az O(n) extra memóriaigény jelentős lehet nagy adathalmazok esetén, különösen, ha a memória korlátozott.
  • Lassabb lehet kis adathalmazokon: Kis méretű listák esetén a rekurzió és a segédtömb kezelésének overheadje miatt lassabb lehet, mint az egyszerűbb, in-place algoritmusok (pl. beszúrásos rendezés).
  • Rekurziós mélység: A rekurziós hívások miatt a verem (stack) túlcsordulhat nagyon nagy n értékek esetén, bár ez ritka a modern rendszereken. Iteratív változatok léteznek ennek elkerülésére.

Gyakori hibák és tévhitek az összefésülő rendezéssel kapcsolatban

Az összefésülő rendezés implementálása során gyakran előfordulnak bizonyos hibák, amelyeket érdemes elkerülni.

  1. Az összefésülés helytelen megvalósítása: A leggyakoribb hiba az összefésülési fázisban rejlik. Fontos, hogy a két al-lista elemeit helyesen hasonlítsuk össze, és a kisebbiket másoljuk a segédtömbbe, majd a maradék elemeket is megfelelően kezeljük. Egy apró hiba itt az egész rendezést tönkreteheti.
  2. Memória kezelési hibák: A segédtömb helyes méretezése és felszabadítása kritikus. Ha nem megfelelő méretű a segédtömb, vagy nem szabadítjuk fel, az memória szivárgáshoz vagy programhibához vezethet.
  3. Rekurziós alapeset hiánya vagy hibája: Ha az alapesetet (egyelemű lista) nem kezeljük megfelelően, a rekurzió végtelen ciklusba kerülhet, ami verem túlcsordulást okoz.
  4. Nem értjük a stabilitást: Sokan nem tulajdonítanak jelentőséget a stabilitásnak, pedig bizonyos alkalmazásokban ez kulcsfontosságú. Az összefésülő rendezés stabil, ami azt jelenti, hogy az azonos értékű elemek eredeti sorrendje megmarad.

Összefésülő rendezés (Merge Sort) szimuláció megfigyelései

Egy interaktív szimuláció kiválóan alkalmas az összefésülő rendezés működésének megértésére. A szimulációban különösen érdemes megfigyelni a következőket:

  1. A felosztási és összefésülési fa: A szimuláció vizuálisan megjeleníti, ahogy az eredeti lista rekurzívan kisebb és kisebb al-listákra bomlik, egészen az egyelemű listákig. Ez a „felosztási fa” segít megérteni az „oszd meg” elvet. Ezután megfigyelhető, ahogy ezek az egyelemű listák rendezetten összefésülődnek, fokozatosan építve fel a nagyobb, rendezett al-listákat, egészen a teljes rendezett listáig. Ez az „összefésülési fa” a „uralkodj és egyesíts” fázist mutatja be.
  2. Az összefésülés lépései: Figyelje meg részletesen, hogyan hasonlít össze két rendezett al-lista elemeket, és hogyan másolja át a kisebbiket egy ideiglenes segédtömbbe. Láthatja, ahogy a mutatók (i, j, k) mozognak, és ahogy az elemek rendezett sorrendben kerülnek a segédtömbbe.
  3. A segédtömb szerepe: A szimuláció valószínűleg vizuálisan is megjeleníti a segédtömböt, bemutatva, hogyan használja az algoritmus ezt az extra memóriát az összefésüléshez. Ez segít megérteni az O(n) memóriaigényt.
  4. Különböző kezdeti elrendezések: Próbáljon ki különböző kezdeti adatsorokat (pl. már rendezett, fordítottan rendezett, véletlenszerűen rendezett) és figyelje meg, hogy az algoritmus lépéseinek száma és a teljesítménye hogyan marad konzisztensen O(n log n) a különböző esetekben. Ez megerősíti az algoritmus kiszámítható időkomplexitását.
  5. Stabilitás demonstrálása: Ha a szimuláció támogatja az azonos értékű elemek megkülönböztetését (pl. különböző színű, de azonos értékű elemek), akkor megfigyelheti, hogy az összefésülő rendezés megőrzi ezeknek az elemeknek az eredeti relatív sorrendjét, demonstrálva a stabilitás fogalmát.

Gyakran Ismételt Kérdések az Összefésülő Rendezésről (Merge Sort FAQ)

Miért O(n log n) az összefésülő rendezés időkomplexitása?

Az n elemes lista felosztása addig történik, amíg egyelemű listákat nem kapunk, ami log₂n mélységű rekurziós fát eredményez. Minden szinten az összefésülési műveletek összesen O(n) időt vesznek igénybe (mivel minden elemet egyszer kell megvizsgálni). Így a teljes időkomplexitás n * log₂n, azaz O(n log n).

Mi a különbség az összefésülő rendezés és a gyorsrendezés (Quick Sort) között?

Mindkettő „oszd meg és uralkodj” algoritmus, de az összefésülő rendezés stabil és O(n log n) időkomplexitású minden esetben, viszont O(n) extra memóriát igényel. A gyorsrendezés általában gyorsabb a gyakorlatban, átlagos esetben O(n log n), de legrosszabb esetben O(n²) lehet, és O(log n) extra memóriával (vagy O(n) legrosszabb esetben) működik rekurzió esetén, illetve O(1) a helyben végzett változatoknál. Az összefésülő rendezés garantáltan jó teljesítményt nyújt, míg a gyorsrendezés teljesítménye függhet az adatok elrendezésétől és a pivot elem választásától.

Mikor érdemes összefésülő rendezést használni?

Érdemes összefésülő rendezést használni, ha a stabilitás és a garantált O(n log n) teljesítmény fontos szempont, például kritikus rendszerekben, vagy ha nagy adathalmazokat kell rendezni, amelyek memórián kívül is tárolódhatnak (külső rendezés). Ideális választás, ha a memóriaigény nem jelent kritikus korlátot.

Practise it, don't just read it

44 flashcards, a test with explanations and a podcast for this topic. The account is free and you pick up right where you left off.

  • No credit card
  • Web and mobile app
  • 330,000+ students
Start for free

Related topics