2. seminář - Rekurze

TEACHINGZPP2

Rekurze

Rekurzivní funkce

Pojem rekurze, v programování, označuje situaci, kdy funkce volá ve svém těle sebe sama. Rekurze obvykle umožňuje jednoduché řešení problémů, které je možné rozložit na menší podproblémy. Klasickým příkladem používající rekurzi je výpočet n-tého členu Fibonacciho posloupnosti.


    # výpočet n-tého členu Fibonacciho posloupnosti
    # rekurzivní výpočet
    def fib(n):
      if n <= 1: # limitní podmínka
        return n
      return fib(n - 1) + fib(n - 2) # rekurzivní volání

Pokud funkce obsahující rekurzi, jsou označovány jako rekurzivní funkce. Každá rekurzivní funkce obsahuje limitní podmínku, která určuje zda má dojít k opětovnému (rekurzivnímu) volání či nikoliv. Obrázek níže zachycuje průběh rekurzivního volání pro fib(6). Tento průběh se také označuje jako strom rekurzivního volání.

Fibbonaci call stack

Iterativní funkce

Rekurzivní funkce jsou obvykle jednodušší a kratší než jejich iterativní protějšky. Následující zdrojový kód zachycuje iterativní verzi funkce fib.


    # výpočet n-tého členu Fibonacciho posloupnosti
    # iterativní verze
    def fib(n):
      prvni_clen = 0
      druhy_clen = 1
      for i in range(0, n):
        pomocna = prvni_clen
        prvni_clen = druhy_clen
        druhy_clen = pomocna + druhy_clen
      return prvni_clen

Rekurzivní verze je přímočařejí. Nevýhodou je paměťová náročnost rekurze. V případě výpočtu fibbonaciho posloupnoti narůstá počet rekurzivních volání exponenciálně zhledem k n. Řešením je použít koncovou rekurzi, kde není nutné čekat na výpočet jiného rekurzivního volání.


    # výpočet n-tého členu Fibonacciho posloupnosti
    # koncová rekurze
    def fib(n, prvni_clen, druhy_clen):
      if n < 1:
        return prvni_clen
      return fib(n - 1, druhy_clen, prvni_clen + druhy_clen)
      
    print(fib(6, 0, 1))

Úkoly

Naprogramujte rekurzivní i koncově rekurzivní mocnina(zaklad, exponent) vracející hodnotu zakladexponent. Při implementaci funkce nepoužívejte operátor **.
Napište „hloupou“ funkci na výpočet součtu prvků intervalu celých čísel.
Napište rekurzivní funkci pro výpočet faktoriálu zadaného čísla n.
Napište koncově rekurzivní funkci pro výpočet faktoriálu zadaného čísla n.
Napište rekurzivní funkci pro výpočet délky seznamu.
Napiště rekurzivní funkci pascal která vypočítá daný prvek pascalova trojúhelníka.

Výpočet

Každý řádek (kromě prvního) má o jeden prvek víc než předchozí řádek. Řádky vždy začínají a končí jedničkou, ostatní čísla se vypočítají jako součet dvou čísel ležících nad nimi. (Z obrázku by to mělo být vidět; trojúhelník samozřejmě pokračuje směrem dolů donekonečna). Řádky i prvky v nich budeme číslovat od nuly, takže například prvek na řádku číslo 6 (tedy na sedmém řádku), který má na tom řádku pozici 2 (je tedy na řádku třetí), je 15.


    # Pacaluv trojuhelnik
    
                 1
               1   1
             1   2   1
           1   3   3   1
          1  4   6   4   1
        1   5  10  10   5  1
      1   6  15  20  15  6   1
      
   # Přiklady volání
   pascal(0, 0) # -> 1
   pascal(3, 3) # -> 1
   pascal(6, 2) # -> 15