Toggle menu
Toggle preferences menu
Toggle personal menu
Neprihlásený/á
Your IP address will be publicly visible if you make any edits.

Určovanie počtu operácií v rekurzívnych volaniach: Rozdiel medzi revíziami

Poznámkovač
Bez shrnutí editace
Bez shrnutí editace
Riadok 65: Riadok 65:
A takto to bude pokračovať donekonečna... Ale nie? Kedy sa rekurzia skončí? '''Skončí sa vtedy, keď nastane triviálny prípad'''. Triviálny prípad je v tomto prípade '''<math>T(1) = 3</math>'''. To znamená, že funkcia nebude volať samú seba, ak <math>n = 1</math> (pretože vráti iba číslo 3).
A takto to bude pokračovať donekonečna... Ale nie? Kedy sa rekurzia skončí? '''Skončí sa vtedy, keď nastane triviálny prípad'''. Triviálny prípad je v tomto prípade '''<math>T(1) = 3</math>'''. To znamená, že funkcia nebude volať samú seba, ak <math>n = 1</math> (pretože vráti iba číslo 3).


To znamená, že do nášho rozpisu musíme namiesto posledného rekurzívneho volania dať tento triviálny prípad:
To znamená, že do nášho rozpisu musíme namiesto posledného rekurzívneho volania dať triviálny prípad:


<math display="block">T(n) = \overbrace{\color{green}T(n - 4)}^{\text{sem}} + 5 + 5 + 5</math>
<math display="block">T(n) = \overbrace{\color{green}T(n - 4)}^{\text{sem}} + 5 + 5 + 5</math>


Musíme to ale spraviť tak, aby sa nám nestratilo <math>n</math> (aby sme to stále mohli vyjadriť pre ľubovoľné <math>n</math>). Inými slovami, nemôžme spraviť jednoducho toto:
Vsunieme tam <math>T(1)</math> (čo je vlastne číslo 3) pretože to je jediný prípad ktorý neobsahuje rekurziu. Vďaka tomu bude funkcia vyjadrená nerekurzívne (analyticky):
 
<math display="block">T(n) = \overbrace{T(1)}^{3} + 5 + 5 + 5 + \cdots</math>
 
Posledná otázka je, že koľkokrát sa tam bude nachádzať sčítanie čísla 5. Ak sa pozrieme na pôvodné výpočty vyššie, vidíme že čísiel 5 je tam vždy o 1 menej ako <math>n</math>:


<math display="block">\begin{align}
<math display="block">\begin{align}
T(n) &= \cancel{\color{red}T(1)} + 5 + 5 + 5 \\
T\overbrace{(1)}^{n = 1} &= 3 \\
T(n) &= 3 + 5 + 5 + 5 \longleftarrow \text{takto predsa tá funkcia definovaná nie je...} \\
T(2) &= T(\overbrace{n - 1}^{\color{red}n = 2}) + \overbrace{5}^{{\color{orange}n} - 1} \\
T(3) &= T(\overbrace{n - 2}^{\color{red}n = 3}) + \overbrace{5 + 5}^{{\color{orange}n} - 1} \\
T(4) &= T(\overbrace{n - 3}^{\color{red}n = 4}) + \overbrace{5 + 5 + 5}^{{\color{orange}n} - 1} \\
T(5) &= T(\overbrace{n - 4}^{\color{red}n = 5}) + \overbrace{5 + 5 + 5 + 5}^{{\color{orange}n} - 1} \\
\cdots \\
\end{align}</math>
\end{align}</math>


Ale, zámer zostáva rovnaký – vsunúť tam <math>T(1)</math>, pretože toto je jediný prípad ktorý neobsahuje rekurziu. Teda nám to umožní funkciu vyjadriť nerekurzívne (analyticky). Musíme sa nad tým zamyslieť inak – ak máme nejaké <math>n</math>, čo musíme spraviť aby sme z tohto <math>n</math> spravili číslo 1?
Funkciu <math>T(n)</math> môžeme teda zapísať ako:


Ak odčítame dve rovnaké hodnoty, dostaneme nulu. A potom stačí pripočítať 1 a máme triviálny prípad. Takže, niečo takéto by fungovalo:
<math display="block">\begin{align}
T(n) &= T(1) + 5 \times (n - 1) \\
&= 3 + 5 \times (n - 1) \\
&= 3 + 5n - 5 \\
T(n) &= {\color{green}5n - 2} \\
\end{align}</math>


<math display="block">T(n) = T(\overbrace{n - n + 1}^{\text{toto bude vždy}\ 3}) + 5 + 5 + 5</math>
Bohužiaľ, nepomôže nič iné ako iba pozrieť sa na funkciu a všimnúť si vzťah medzi <math>n</math> a postupnosťou čísiel. Odporúčam pre rekurziu vypočítať viacero príkladov, keďže sú to veci nad ktorými sa treba zamyslieť logicky a pre netrénované oko to môže byť dosť náročné.


{{Téma|Oblast=Kategória:Algoritmy a výpočtová zložitosť|Poradie=25}}
{{Téma|Oblast=Kategória:Algoritmy a výpočtová zložitosť|Poradie=25}}
[[Kategória:Algoritmy a výpočtová zložitosť]]
[[Kategória:Algoritmy a výpočtová zložitosť]]

Verzia z 17:02, 25. marec 2025

Vyjadrenie funkcie T(n) analyticky (nerekurzívne), určovanie výpočtovej zložitosti v rekurzívnych funkciách.


Určenie konkrétnej hodnoty rekurzívnej funkcie výpočtovej zložitosti

Už vieme určovať výpočtovú zložitosť v metódach, ktoré nie sú rekurzívne. Ale čo ak funkcia volá samú seba? Majme napríklad funkciu T(n) definovanú takto:

T(n)=T(n1)+5T(1)=3

Funkcia T(n) odkazuje na samú seba, pričom vieme že pre n=1 je hodnota číslo 3. Toto sa nazýva triviálny prípad – je to bod, v ktorom sa rekurzívne volanie zastaví. Toto bude veľmi dôležité, pretože rekurzívne funkcie sa musia skôr či neskôr zastaviť (nemôžeme ich volať donekonečna).

Aby sme si vedeli lepšie predstaviť ako rekurzívne funkcie fungujú, poďme vypočítať, akú hodnotu bude mať T(5):

T(n)=T(n1)+5T(1)=3T(2)=T(21)+5=T(1)+5=3+5=8T(3)=T(31)+5=T(2)+5=8+5=13T(4)=T(41)+5=T(3)+5=13+5=18T(5)=T(51)+5=T(4)+5=18+5=23

Ako vidíme, T(5)=23. Ide iba o postupné nahrádzanie premennej n, pričom ak chceme vypočítať určitú hodnotu, musíme v tomto prípade poznať aj všetky predošlé hodnoty. Avšak, čo by sa stalo ak by sme chceli vypočítať T(1000)? Ak by sme to počítali manuálne, trvalo by to strašne dlho. Veľmi veľké hodnoty by robili problém aj najrýchlejším počítačom, obzvlášť ak by rekurzívne volania boli komplikovanejšie.

Našťastie, pre tento prípad vieme rekurzívne funkcie vyjadriť analyticky (teda, nerekurzívne) – to znamená že pre dané n vieme vypočítať konkrétnu hodnotu bez toho, aby sme volali funkciu rekurzívne.

Pri analýze funkcie musíme postupovať od čísla n a postupne sa vnárať hlbšie a hlbšie do rekurzie. Pre príklad vyššie by sme postupovali takto:

T(n)=T(n1)+5T(n1)=?

Ako všeobecne vyjadríme T(n1)? Tak, že zoberieme všeobecnú definíciu funkcie T(n) a namiesto n dosadíme n1:

T(n)=T(n1)+5T(n1)=T(n1n1)+5T(n1)=T(n2)+5

To dáva zmysel – ak chceme vyjadriť T(n1), musíme k hodnote predtým (T(n2)) pripočítať 5. Inými slovami, vždy sa hodnota pre nejaké n vyjadrí tak, že sa k hodnote predtým (n1) pripočíta 5. Ale nesmieme zabudnúť, že T(1)=3.

Ak by sme pokračovali vo vyjadrovaní menších a menších n, vyzeralo by to nejako takto. n znižujeme preto, lebo sa chceme priblížiť ku triviálnemu prípadu: číslu 3 (predpokladá sa, že 3<n):

T(n1)=T(n2)+5T(n2)=T(n3)+5T(n3)=T(n4)+5

Teraz sme si vyjadrili pomocné funkcie a vnorili sa hlbšie do rekurzie. Tieto funkcie musíme dosadiť späť do pôvodného T(n), teda:

T(n)=T(n1)+5=T(n2)+5+5=T(n3)+5 + 5=T(n4)+5 + 5 + 5

A takto to bude pokračovať donekonečna... Ale nie? Kedy sa rekurzia skončí? Skončí sa vtedy, keď nastane triviálny prípad. Triviálny prípad je v tomto prípade T(1)=3. To znamená, že funkcia nebude volať samú seba, ak n=1 (pretože vráti iba číslo 3).

To znamená, že do nášho rozpisu musíme namiesto posledného rekurzívneho volania dať triviálny prípad:

T(n)=T(n4)sem+5+5+5

Vsunieme tam T(1) (čo je vlastne číslo 3) pretože to je jediný prípad ktorý neobsahuje rekurziu. Vďaka tomu bude funkcia vyjadrená nerekurzívne (analyticky):

T(n)=T(1)3+5+5+5+

Posledná otázka je, že koľkokrát sa tam bude nachádzať sčítanie čísla 5. Ak sa pozrieme na pôvodné výpočty vyššie, vidíme že čísiel 5 je tam vždy o 1 menej ako n:

T(1)n=1=3T(2)=T(n1n=2)+5n1T(3)=T(n2n=3)+5+5n1T(4)=T(n3n=4)+5+5+5n1T(5)=T(n4n=5)+5+5+5+5n1

Funkciu T(n) môžeme teda zapísať ako:

T(n)=T(1)+5×(n1)=3+5×(n1)=3+5n5T(n)=5n2

Bohužiaľ, nepomôže nič iné ako iba pozrieť sa na funkciu a všimnúť si vzťah medzi n a postupnosťou čísiel. Odporúčam pre rekurziu vypočítať viacero príkladov, keďže sú to veci nad ktorými sa treba zamyslieť logicky a pre netrénované oko to môže byť dosť náročné.