Big O (Landau) jelölés — algoritmusok idő- és memória-komplexitása

A Big O jelölés az algoritmusok összehasonlításának egyik alapvető eszköze. Arra szolgál, hogy leírjuk, hogyan nő egy algoritmus futási ideje vagy memóriaigénye a bemenet méretének növekedésével — azaz megmutatja a probléma és az algoritmus növekedési rendjét.

Rövid történet és elnevezés

A Big O jelölést Paul Bachmann (1837–1920) használta először az 1896-os második kiadású "Analytische Zahlentheorie" című munkájában; később Edmund Landau (1877–1938) tette általánossá. Emiatt a jelölést gyakran Landau-szimbólumoknak nevezik. A kifejezés a „függvény rendje” fogalmából ered, ami a függvények növekedési ütemére utal. A Big O-t gyakran alkalmazzák a probléma komplexitási osztályának meghatározására is.

Mit jelent formálisan a Big O?

Formálisan azt mondjuk, hogy egy f(n) függvény az O(g(n)) osztályba tartozik, ha léteznek pozitív konstansok c és n0 úgy, hogy minden n ≥ n0 esetén f(n) ≤ c·g(n). Ez azt jelenti, hogy g(n) egy felső korlátot ad f(n) növekedésére konstans tényezővel eltolva — a nagy n esetén megjelenő viselkedésre fókuszálunk, az alacsonyabb rendű tagokat és konstansokat figyelmen kívül hagyjuk.

Miért hasznos a Big O?

A Big O gyakran a legrosszabb eset szerinti (worst-case) futási időt írja le: megmutatja, hogy legrosszabb körülmények között mennyi időt vagy memóriát igényel egy algoritmus, anélkül hogy ténylegesen futtatnánk a programot egy adott gépen. Ez hasznos, mert különböző számítógépek különböző hardverrel rendelkezhetnek, és a tényleges futási idő géptől függően változik; a Big O viszont hardverfüggetlen összehasonlítást nyújt. A Big O mindig a legrosszabb esetet feltételezve konzisztens viszonyítást ad: az O ( 1 ) {\displaystyle O(1)}{\displaystyle O(1)} mindig gyorsabban fog elkészülni, mint az O ( n ! ) {\displaystyle O(n!)}{\displaystyle O(n!)}, mivel a két rend szerinti növekedésük drasztikusan eltér.

Gyakori komplexitási osztályok és tipikus példák

  • O(1) — konstans idő: pl. egy tömb adott indexű eleméhez való hozzáférés, vagy egy változó értékének lekérése.
  • O(log n) — logaritmikus: pl. bináris keresés rendezett tömbben.
  • O(n) — lineáris: egyszerű egysoros bejárás (egy ciklus, amely minden elemen egyszer végigmegy).
  • O(n log n) — tipikus rendezőalgoritmusok, pl. összeolvasztásos rendezés (merge sort), gyorsabb rendezési eljárások átlagos esete.
  • O(n^2) — kvadratikus: kétszer egymásba ágyazott ciklus; gyakori egyszerű rendezési algoritmusoknál (pl. buborékrendezés, beillesztéses rendezés rossz esetben).
  • O(2^n) — exponenciális: sok visszalépéses (backtracking) megoldás, pl. teljes halmaz- vagy részhalmaz-iteráció rekurzív formában.
  • O(n!) — faktoriális: pl. összes permutáció vizsgálata (például a teljes permutációk generálása problémáknál).

Idő- és memória-komplexitás

A Big O ugyanúgy alkalmazható memóriaigényre (memóriára) mint futási időre: leírhatjuk, hogy egy algoritmus mekkora extra memóriahelyet igényel a bemenet méretének függvényében. Fontos különbség, hogy egy algoritmus időbeli és tárhelybeli teljesítménye gyakran ellentmondó kompromisszumokat igényel (például több gyorsabb memória használata vs. lassabb, de kisebb memóriahasználat).

Hogyan számoljuk ki egyszerű esetekben?

  • Egyszerű ciklus: for(i=0; i<n; i++) → O(n).
  • Kettős ciklus, mindkettő n-ig: for(i=0; i<n; i++) for(j=0; j<n; j++) → O(n^2).
  • Bináris keresés: ismételt félig levágás → O(log n).
  • Rendezés (merge sort): T(n) = 2T(n/2) + O(n) megoldása → O(n log n).

Finomságok és gyakorlati megjegyzések

  • Konstansok és alacsonyabb rendű tagok elhagyása: a Big O a növekedés aszimptotikus viselkedésére koncentrál; így kis n és konstans tényezők még befolyásolhatják a tényleges futást, de nagy n esetén ezek elhanyagolhatók.
  • Worst-case vs. average-case vs. best-case: Big O általában legrosszabb esetet jelöl, de gyakran fontos az átlagos (average-case) vagy amortizált viselkedés is (például hash-tábláknál).
  • Más Landau-szimbólumok: a nagy-Theta (Θ) a pontos (felső és alsó korlát együttes) viselkedést jelöli; a nagy-Omega (Ω) alsó korlátot jelent.
  • Gyakorlati korlátok: Big O nem ad információt a valós konstansokról és a memóriahatékonyság apró részleteiről; két O(n) algoritmus között lehet jelentős gyakorlati különbség, ezért mindig hasznos empirikusan is mérni a kódot.

Összefoglalás

A Big O (Landau) jelölés egy egyszerű és erőteljes eszköz az algoritmusok idő- és memória-komplexitásának összehasonlítására, amely a bemenet méretével növekvő viselkedés aszimptotikus felső korlátát adja meg. Bár nem helyettesíti a részletes mérési és profilozási munkát, segít elkerülni olyan megoldásokat, amelyek elméletben skálázódási problémákat okoznak nagy bemeneteknél.

Példák

A következő példák mindegyike Python nyelven írt kódot használ. Vegye figyelembe, hogy ez nem a Big O típusok teljes listája.

Állandó

O ( 1 ) {\displaystyle O(1)}{\displaystyle O(1)} . Mindig ugyanannyi időt vesz igénybe, függetlenül a bemenettől. Vegyünk például egy olyan függvényt, amely elfogad egy egész számot (x-nek nevezve), és annak kétszeres értékét adja vissza:

def double(x): return x * 2 #Return the value of x times 2

A bemenet elfogadása után ez a függvény mindig tesz egy lépést, hogy visszaadjon egy kimenetet. Ez azért állandó, mert mindig ugyanannyi időt vesz igénybe, tehát O ( 1 ) {\displaystyle O(1)}{\displaystyle O(1)} .

Lineáris

O ( n ) {\displaystyle O(n)}{\displaystyle O(n)} . Növekszik a bemenet méretének megfelelően, amelyet n {\displaystyle n}n jelez. Tegyük fel, hogy egy függvény n-t fogad el, és 1-től n-ig minden számot visszaad:

def count(n): i = 1 #Elkészítünk egy "i" nevű számlálót 1 értékkel while i <= n:   #Míg i kisebb vagy egyenlő n-nel print(i) #Kiírja i értékét i = i + 1 #Újra definiálja i-t "i + 1 értékének".

Ha az 5 értéket adnánk meg, akkor ez az 1 , 2 , 3 , 4 , 5 {\displaystyle 1,2,3,4,5} kimeneti értéket adna ki. {\displaystyle 1,2,3,4,5}, amihez 5 ciklusra lenne szükség. Hasonlóképpen, ha 100-at adnánk meg, akkor 1 , 2 , 3...98 , 99 , 100 {\displaystyle 1,2,3...98,99,100}{\displaystyle 1,2,3...98,99,100} lenne a kimenet, amihez 100 ciklusra lenne szükség. Ha a bemenet n {\displaystyle n}n, akkor az algoritmus futási ideje minden alkalommal pontosan n {\displaystyle n} nciklus, tehát O ( n ) {\displaystyle O(n)}{\displaystyle O(n)} .

Factorial

O ( n ! ) {\displaystyle O(n!)}{\displaystyle O(n!)} . Faktoriális mennyiségben növekszik, vagyis a felhasznált idő a bemenettel együtt masszívan növekszik. Tegyük fel például, hogy öt várost szeretnénk meglátogatni a világon, és minden lehetséges sorrendet (permutációt) látni szeretnénk. Egy algoritmus, amit a Python itertools könyvtárát használva írhatnánk, a következő:

import itertools #Importáljuk az itertools könyvtárat cities = ['London', 'Paris', 'Berlin', 'Amsterdam', 'Rome'] #A kiválasztott városok tömbje def permutations(cities):                    #Városok tömbjének felvétele bemenetként: for i in itertools. permutations(cities): #Minden egyes permutációnkhoz (az "i" változóhoz rendelve) print(i) #Kimenet i

Ez az algoritmus kiszámítja a városaink minden egyes egyedi permutációját, majd kiadja azt. A kimeneti példák a következők:

('London', 'Párizs', 'Berlin', 'Amszterdam', 'Róma') ('London', 'Párizs', 'Berlin', 'Róma', 'Amszterdam') ('London', 'Párizs', 'Amszterdam', 'Berlin', 'Róma') ... ('Róma', 'Amszterdam', 'Párizs', 'Berlin', 'London') ('Róma', 'Amszterdam', 'Berlin', 'London', 'Párizs') ('Róma', 'Amszterdam', 'Berlin', 'Párizs', 'London')

Itt a bemeneti listánk 5 elem hosszú, és minden egyes kiválasztásnál a fennmaradó lehetőségeink száma 1-gyel csökken. Más szóval az 5 bemenetünk 5 × 4 × 3 × 2 × 1 {\displaystyle 5\times 4\times 3\times 2\times 1}{\displaystyle 5\times 4\times 3\times 2\times 1} elemet választ (vagy 5 ! {\displaystyle 5!}{\displaystyle 5!} ). Ha a bemenetünk n {\displaystyle n} nváros hosszú, akkor a kimenetek száma n ! {\displaystyle n! }{\displaystyle n!} ; más szóval, feltételezve, hogy minden permutáción végigmegyünk, O ( n ! ) {\displaystyle O(n!)} {\displaystyle O(n!)}ciklusra lesz szükségünk a befejezéshez.

Little-o jelölés

A Big O szigorúbb változata a little-o. A nagy O és a little-o között az a különbség, hogy a little-o egy szigorú felső korlát: míg az O ( n ) {\displaystyle O(n)} {\displaystyle O(n)}azt jelenti, hogy a befejezési idő a bemeneti méret alapján a maximumra nő, addig az o ( n ) {\displaystyle o(n)} {\displaystyle o(n)}azt jelenti, hogy a befejezési idő általában ez alatt az idő alatt marad. Más szóval a Big O feltételezi, hogy minden ciklus a leghosszabb utat választja, és a folyamat a lehető leghosszabb ideig tart, míg a little-o reálisabb a tényleges futási időkkel kapcsolatban; ha a ciklusok száma egy hatoldalú kocka dobásán alapul, a Big O mindig 6-os számot feltételez, míg a little-o más számok dobásának egyenlő valószínűségét veszi figyelembe.

Kérdések és válaszok

K: Mi az a Big O jelölés?


V: A Big O jelölés a különböző függvények növekedési rátáinak összehasonlítására szolgáló módszer, amelyet gyakran használnak különböző algoritmusok hatékonyságának összehasonlítására annak kiszámításával, hogy mennyi memória és idő szükséges a teljesítéshez. Arra is használható, hogy megállapítsuk, mennyire összetett egy probléma.

K: Ki használta először ezt a jelölést?


V: Paul Bachmann (1837-1920) matematikus használta először ezt a jelölést 1896-ban megjelent "Analytische Zahlentheorie" című könyvében.

K: Mit jelent a Big O?


V: A Big O a "függvény rendje" rövidítése, amely a függvények növekedési sebességére utal.

K: Hogyan használják a Big O-t?


V: A Big O jelölést arra használják, hogy megtalálják a függvény növekedési ütemének felső korlátját (a lehető legnagyobb összeget), vagyis kiszámítják, hogy mennyi idő alatt lesz a leghosszabb egy bemenetből kimenet. Ez azt jelenti, hogy az algoritmusokat aszerint lehet csoportosítani, hogy a legrosszabb esetben mennyi időbe telik, ahol minden alkalommal a leghosszabb útvonalat választják.

K: Mik azok a Landau-szimbólumok?


V: A Landau-szimbólumok a Big O jelölésre utalnak, amelyet Edmund Landau (1877-1938) után neveztek el, aki ezt a jelölést népszerűvé tette.

K: Miért hasznos a Big O?



V: A Big O lehetővé teszi a sebesség mérését anélkül, hogy a programokat számítógépeken futtatnánk, mivel mindig a legrosszabb esetet feltételezi, így a számítógépek közötti hardverbeli különbségektől függetlenül konzisztens. Azt is megmutatja, hogy mennyire hatékony egy algoritmus anélkül, hogy ténylegesen futtatni kellene egy számítógépen.

AlegsaOnline.com - 2020 / 2025 - License CC3