Ako "odmerať" efektívnosť?

Už sme si povedali, že pre zadaný konkrétny vstup vieme algoritmus odsimulovať a spočítať počet krokov, ktoré spraví. Predstavme si, že toto spravíme pre všetky možné vstupy, ktoré majú veľkosť nanavýš NN. Následne nájdeme najhorší spomedzi nich, t. j. ten, ktorý donúti náš algoritmus urobiť najviac krokov. Označme tento počet krokov f(N)f\left( N \right). Túto funkciu budeme volať časová zložitosť algoritmu.

Inými slovami, na spracovanie ľubovoľného vstupu veľkosti najviac NN určite stačí spraviť f(N)f\left( N \right) krokov.

Vráťme sa k algoritmu z Príkladu 2. Aký je najhorší vstup veľkosti najviac NN? Inými slovami, ktoré najviac NN-prvkové pole si vynúti najviac krokov výpočtu? Ľahko si všimneme, že:

  • prvý krok sa vykoná práve NN-krát,
  • druhý a tretí krok sa vykonajú práve N(N1)2\frac{N\left( N - 1 \right)}{2} -krát,
  • štvrtý krok sa vykoná najviac N(N1)2\frac{N\left( N - 1 \right)}{2} -krát.

Nuž a zjavne ak budú na začiatku prvky poľa A v klesajúcom poradí, štvrtý krok sa zakaždým vykoná. Toto je teda najhorší možný vstup. Náš algoritmus na ňom spraví 3N(N1)2+N=1.5N20.5N\frac{3 N\left( N - 1 \right)}{2} + N = 1.5 N^2 - 0.5N krokov. Teda jeho časová zložitosť je f(N)=1.5N20.5Nf\left( N \right)= 1.5 N^2 - 0.5N .

Je pomerne očividné, že takto určiť presnú časovú zložitosť pre zložitejší algoritmus by bolo ťažké, ak nie nemožné. Ukazuje sa ale, že to nie je ani nutné. V našom príklade môžeme napríklad zanedbať člen 0.5N-0.5N. V porovnaní s 1.5N21.5N^2 je totiž zanedbateľný a takmer neovplyvní čas behu programu. Na to, aby sme vedeli posúdiť rýchlosť nášho programu, nám bohate stačí výsledok: "f(N)f\left( N \right) je približne rovné 1.5N21.5N^2". Ako ukážeme o chvíľu, ani na konkrétnej konštante 1.51.5 príliš nezáleží.

Predstavme si dva algoritmy: jeden s časovou zložitosťou N2N^2, druhý 0.001N30.001N^3. Ľahko vypočítame, že pre NN väčšie ako 10001\,000 je už prvý algoritmus rýchlejší – a s rastúcim NN sa tento rozdiel rýchlo zväčšuje. Kým prvý algoritmus vyrieši vstup veľkosti N=20000N = 20\,000 za niekoľko sekúnd, druhý už bude potrebovať minúty.

Zjavne podobná situácia nastane vždy, keď jedna z funkcii udávajúcich časovú zložitosť rastie asymptoticky rýchlejšie ako druhá. (T. j. keď pre NN idúce do nekonečna ide aj podiel týchto dvoch funkcií do nekonečna.) Bez ohľadu na konkrétne konštanty bude algoritmus s časovou zložitosťou CN2C\cdot N^2 lepší od algoritmu s časovou zložitosťou DN3D \cdot N^3na skoro všetkých možných vstupoch. A na tomto pozorovaní založíme naše formálne definície.