(složitost v nejlepším, nejhorším, průměrném případu, očekávaná složitost)
Složitost algoritmu vyjadřuje náročnost algoritmu na různé zdroje v průběhu výpočtu. Tyto zdroje potom určují tzv. míry složitosti, z nichž nejvýznamnější z hlediska informatiky jsou:
Abychom mohli korektně zavést časovou i prostorovou složitost, je třeba nejprve porozumět pojmům délka výpočtu a množství spotřebované paměti.
Přesné definice těchto pojmů závisí na výpočetním modelu – např. Turingův stroj, RAM, funkcionální jazyk, while-program. Tyto modely jsou z hlediska vyjadřovací síly ekvivalentní (z hlediska výpočetní složitosti samozřejmě ne). Pro zavedení pojmu délka výpočtu budeme uvažovat funkcionální jazyk a imperativní jazyk zastoupený while-programem, abychom zdůraznili efekt referenční transparentnosti funkcionálního jazyka a stavového transformátoru jazyka imperativního.
Při časové složitosti je důležité rozlišovat mezi dvěma pojmy:
Platí: časová složitost problému = časová složitost optimálního („nejrychlejšího“) algoritmu pro daný problém
Příklad problému a algoritmů, které problém řeší
SelectSort
, QuickSort
, HeapSort
, …
Časovou složitost problému mám zadefinovanou pomocí časové složitosti algoritmu. Tu si zadefinujeme pomocí funkce délky výpočtu algoritmu.
Nechť je výraz. Délkou výpočtu výrazu rozumíme dobu nutnou pro pro vyhodnocení daného výrazu, a značíme ji . je rovna součtu délek vyhodnocení všech výrazů, které obsahuje. Vyhodnocení elementárních aritmetických, logických, relačních operací nad skalárními operandy je konstantní. Proto i délku výpočtu výrazu, který obsahuje pouze jednoduché operace, považujeme za konstantní.
Délka vyhodnocování závisí také na vyhodnocovací strategii (viz AP7, IN7 Vyhodnocování výrazů).
Pro jazyky, které nejsou referenčně transparentní (např. imperativního paradigmatu) musí funkce zohledňovat ještě stav před výpočtem výrazu a změnu stavu po výpočtu. Funkce pro jazyky, které nejsou referenčně transparentní, tak bude mít o jeden argument navíc, což bude stav výpočetního systému před výpočtem výrazu , tedy předpis funkce bude vypadat .
Víme, že délka výpočtu algortimu záleží od délky vstupu. Podle toho, o jaký případ se zajímáme (při dané délce vstupu), rozlišujeme:2)
Je-li In množina všech vstupních dat pro algoritmus A, pak pro zavedeme číslo , které nazveme velikost vstupní hodnoty . Časovou složitost zavedeme jako funkci takto:4)
Pro jazyky, které nejsou referenčně transparentní označíme počáteční stav výpočtu, který odpovídá umístění hodnoty na vstupu a funkci zavedeme jako:
Časová složitost algoritmu je tedy funkce, která pro každou velikost vstupních dat je rovná délce nejdelšího výpočtu na všech možných datech této velikosti, t.j. rovná se složitosti v nejhorším případě.
Pro další práci s funkcí délky výpočtu výrazu a pojmem časová složitost algoritmu musíme umět porovnat časové složitosti dvou algoritmů. To uděláme tak, že porovnáme jejich délky výpočtů v závislosti na vstupu v nejhorším případě. Avšak nebudeme porovnávat algoritmy podle absolutní hodnoty délky výpočtu pro dané n; budeme se zajímat pouze a o asymptotické chování funkcí délky výpočtu.
Neformálně: Jestli se zajímáme o asymptotické chování složitosti algoritmu, pak můžeme zanedbat všechny konstanty a jestli je funkce délky výpočtu ve tvaru součtu funkcí (např. polynom), vybereme pouze funkci která roste nejrychleji (např. vedoucí člen polynomu s koeficientem rovným 1).
Definujeme následující množiny funkcí:
Množiny funkcí sloužící k asymptotickému porovnání rychlosti růstu dvou funkcí
Při analýze složitosti nás většinou zajímají tři druhy složitosti:5)
Pro určování časové složitosti algoritmu můžeme použít dva přístupy. Nechť A je algoritmus skládající se z kroků :7)
Poznamenejme, že amortizovaná složitost nepředstavuje další typ složitosti k dříve uvedeným (tj. nejlepší/nejhorší/průměrný případ), ale pouze způsob výpočtu složitosti.
Jednotlivé techniky představíme na příkladě zásobníku.
Zásobník
Push(S, x)
Pop(S)
Multipop(S, k)
– vybere k prvků z S, resp. vyprázdní zásobník, je-li |S| < k. Zásobník – příklad na zjištění složitosti klasickou metodou (neamortizovanou složitost)8)
Pop, Push a Multipop
. Push
a Pop
mají složitosti 1. V posloupnosti n operací má Multipop
v nejhorším případě složitost n. Proto celá posloupnost má v nejhorším případě složitost . Operace rozdělíme do skupin a analyzujeme složitost celé skupiny operací současně.9)
Zásobník – příklad na zjištění amortizované složitosti metodou seskupení
Push
, suma jejich složitostí nepřesáhne n Pop
a Multipop
, suma jejich složitostí (= počet prvků vybraných ze zásobníku) nemůže být větší než počet vykonaných operací Push
(=počet prvků vložených do zásobníku). Složitost cele skupiny proto nepřesáhne n.
Celá posloupnost ma v nejhorším případě složitost .
Každé operaci přiřadíme kredit (číslo), které může být různé od její skutečné ceny (složitosti). Při realizaci operace zaplatíme její cenu kredity podle těchto pravidel:10)
Počátečný stav účtu je 0 kreditů. Jestli během celého výpočtu zůstane počet kreditů na účtu nezáporný, pak součet kreditů vykonaných operací je cena vykonaných operací.
Platí: Amortizovaná cena operace = počet kreditů přiřazených operaci
Zásobník – příklad na zjištění amortizované složitosti metodou účtů
Operace | Cena | Kredity |
---|---|---|
Push | 1 | 2 |
Pop | 1 | 0 |
Multipop | 0 |
Operaci Push
zaplatíme 1 kreditem, 1 kredit dáme na účet. Operace Pop
a Multipop
zaplatíme kredity z účtu. Lehce dokážeme, že během celého výpočtu platí invariant počet kreditů na účtě je rovný počtu prvků v zásobníku. Z toho plyne, že zůstatek na účtě nikdy neklesne pod 0.
Celková složitost posloupnosti n operací je součet kreditů vykonaných operací .
Operace se realizují na datovou strukturou. Potenciálova funkce přiřadí každé hodnotě (obsahu) datové struktury číslo. Uvažujme posloupnost n operací, nechť skutečná cena i-té operace v této posloupnosti je ci. Označme D0 iniciální hodnotu datové struktury a Di její hodnotu po vykonání i-té operace.
Definujeme amortizovanou cenu i-té operace, , předpisem
Součet amortizovaných cen operací je
Za předpokladu, že platí , t.j. součet amortizovaných cen operací je horním odhadem pro složitost celé posloupnosti operací.
Aby jsme zabezpečili platnost podmínky , definujeme potenciálovou funkci tak, aby pro každou hodnotu D datové struktury platilo, že potenciál je aspoň tak velký, jak potenciál počáteční hodnoty datové struktury.11)
Zásobník – příklad na zjištění amortizované složitosti metodou potenciálové funkce
Push | |
Pop | |
Multipop |
Pro všechny platí .
Proto složitost celé posloupnosti je
Shkodran Gerguri
Adam Libuša, 173122[AT]mail.muni.cz
Otázku si přečetl pan RNDr. Libor Škarvada a rámcově prošel. Jeho podněty pro doplnění textu, opravy nesrovnalostí a odstranění matoucích či k otázce se nevztahujících textů byly do otázky zaneseny. Tato kontrola je jen rámcová, stále se může stát, že v otázce zůstala zapomenutá chybka či nesrovnalost, vyučující za toto nenese odpovědnost, berte tuto rámcovou kontrolu jako formu pomoci od vyučujících pro studenty.
Diskuze
co se ucite k teto otazce? co je ocekavana a prumerna slozitost? Prumerna je asi amortizovana, ne? Moc nevim, co si k teto otazce pripravit. Napada me ukazat na nejakym vhodnym prikladu jednotlive slozitosti a tim to asi konci. Mozna jeste zminit slozitostni tridy (podobne jak to je v otazce Slozitost).
Ono je tam toho vic. Napr. metoda uctu, metoda potencialove funkce - to vse se pouziva pri amortizovane slozitosti.
Ja to teda skúsim vypracovať…
Diky.
sorry..obnovil jsem stranku a vlozilo se mi to tam znovu. Jinak dik vsem, kdo pracuji na vypracovani teto otazky.
Tak jsem to prosel, a zda se mi, ze tam nic nechybi.
Ok, díky, teraz ešte keby sa na to pozrel nejaký vyučujúci..
Ok, zkusim napsat Dr. Skarvadovi, prof. Cerne bych radeji nepsal, aby si to nevylozila nejak zle.
Tak ako nie je to od slova do slova prepísané z jej materiálov, ale niečo na tom asi bude :)
Takhle jsem to nemyslel :), spis jde o to, aby ji ta zadost neprisla moc troufala. Kazdopadne jsem uz napsal Dr. Skarvadovi, tak snad se na to podiva.
Otazka je vypracovana pekne, diki :) Mam len jednu pripomienku:
Podla mna zlozitost v priemernom pripade sa nerovna ocakavanej zlozitosti -
1)pride mi to nelogicke preco by do zadania davali 2 terminy, ktore znamenaju to iste
2)myslim si, ze ocakavana zlozitost je nieco ako kolko platnych vystupov ocakavame, tak podla toho sa urci zlozitost - vid Karp-Rabinov alg., kde ocakavana zlozitost je O((n-m+1) + cm), kde c je pocet platnych posunov. Na druhu stranu, zlozitost v priemernom pripade Karp-Rabinovho alg. neviem ako by sa urcovala :)
Diky, snažil som sa :) Nikde som v skriptách nemohol násť definíciu očakávanej zložitosti, tak som čerpal odtiaľto. Tie dve rôzne podotázky - ja viem, tiež ma to napadlo, ale tak som si povedal prečo nie, chceli možno povedať, že to je to isté. Alebo sa možno len rôznia termíny z rôzných zdrojov.
Na druhú stranu ak zoberiem ten pojem z Karp-Rabinovho algoritmu “ nieco ako kolko platnych vystupov ocakavame, tak podla toho sa urci zlozitost“, tak sa mi to zdá dosť podobné tomuto: „počítá se jako střední hodnota náhodné složitosti při nějakém rozložení vstupních dat“ :). Každopádne ak nájdeš niekde nejakú lepšiu definíciu očakávanej zložitosti, kľudne to tam prepíš.