+ All Categories
Home > Documents > 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li...

4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li...

Date post: 05-Aug-2021
Category:
Upload: others
View: 3 times
Download: 0 times
Share this document with a friend
29
4 Rekurze
Transcript
Page 1: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

4 Rekurze

Page 2: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Co je rekurze

Rekurzivní algoritmus

– Odkazuje přímo nebo nepřímo na sebe

Rekurzivní datová struktura

– obsahuje odkazy na datové struktury stejného

druhu

Seznam, strom

Rekurzivní podprogram

– Naprogramování rekurzivního algoritmu

Page 3: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Příklad

Rekurzivní zpracování binárního stromu

(přímé)

1. Je-li strom prázdný, skončíme

2. Jinak zpracujeme údaj v kořeni

3. Zpracujeme tímto algoritmem levý podstrom

4. Zpracujeme tímto algoritmem pravý

podstrom

Page 4: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Rekurze

Obecný tvar rekurzivního algoritmu P

P ≡ C[Si, P]

– C označuje kompozici (složení) algoritmů

– Si jsou jiné algoritmy neobsahující odkaz na P

Požadavek: konečnost rekurze

– Použití odkazu na P musí být vázáno na

splnění určité podmínky B:P ≡ C[Si, if(B) P]

P ≡ C[Sn, if(n > 0) P]

Page 5: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Rekurze v programu

Přímá: f() volá f()

Nepřímá: f() volá g1(), g1() volá g2(), … gn() volá f()

Připomeňme si:

– Každé volání znamená vytvoření rámce zásobníku

– Návrat z funkce znamená zrušení rámce zásobníku

– Možnost vyčerpání paměti při příliš hluboké rekurzi

Page 6: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Příklad: faktoriál

Rekurzivní definice

Rekurzivní implementace

Page 7: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Kdy se rekurzi vyhnout

Rekurzivní algoritmus tvaruP ≡ [S, if(B) P]kde závorky [ ] předepisují nejprve provést S, pak – je-li splněna podmínka B – provést P

Lze nahradit iterativním algoritmem P ≡ [S, while(B) S]

Rekurze zde neznamená zásadní neefektivitu

Page 8: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Kdy se rekurzi vyhnout

Obecně u rekurzivních vztahů tvaru

xn = f(xn-1, … xn-k)

pro k > 1

Vedou k exponenciální složitosti

– Ukážeme na příkladě

Page 9: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Fibonacciova čísla

f0 = 0, f1 = 1, fn = fn-1 + fn-2 pro n > 1

Implementace:

Page 10: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Fibonacciova čísla

Složitost:

Odtud

Protože t1 = t2 = 1, dostaneme, že tn roste

rychleji než 2n/2

Exponenciální složitost!!!

Page 11: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Fibonacciova čísla

Strom volání pro Fibonacci(5)

Page 12: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Fibonacciova čísla

Nerekurzivní implementace: O(n)

Page 13: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Příklady podobných vztahů

Besselovy funkce

Kombinační čísla

Page 14: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Odstraňování rekurze

Algoritmus pro náhradu rekurzivního kódu

nerekurzivním

– Nezmění složitost

– Vede k nepěknému kódu (používá skoky)

– Využívá vlastní zásobník

– Základ pro další úpravy

Page 15: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Odstraňování rekurze

Pro určitost:

– void f(int a, int b, int c);

– Volání: f(3,4,5);

Opakování – co se při volání stane:

– Do zásobníku se uloží skutečné parametry

– Do zásobníku se uloží návratová adresa

– Skočí se na začátek těla funkce

– Vytvoří se v zásobníku lokální proměnné

Page 16: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Odstraňování rekurze

Opakování – co se stane při návratu

– Odstraní se ze zásobníku lokální proměnné

– Odstraní se ze zásobníku skutečné parametry

– Vyjme se ze zásobníku návratová adresa a

skočí se na ni

Problém:

– Nemáme přímý přístup k zásobníku

– Nemáme přímý přístup k adresám míst v kódu

Page 17: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Odstraňování rekurze

Řešení:

– Použijeme vlastní zásobník

– Použijeme návěští a skoky

– Nebudeme vytvářet nové parametry a

proměnné, ale uložíme hodnoty stávajících

Page 18: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Odstraňování rekurze

Postup:

– Na počátku zdrojového kódu

– Pro každé rekurzivní volání

Page 19: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Odstraňování rekurze

– Na konci těla funkce:

Page 20: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Odstraňování rekurze

Příklad:

Page 21: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Příklad: výpočet faktoriálu

Úpravy algoritmu:

– Návratovou hodnot budeme ukládat do

pomocné proměnné

– Není třeba ukládat „návratovou adresu“

(rekurzivní volání na jediném místě)

Page 22: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Odstraňování rekurze

Příklad:

Page 23: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Ackermannova funkce

Funkce , kde N0 = N ∪ {0}

Některé hodnoty

Page 24: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Ackermannova funkce

Lze dokázat, že nejen hodnotu, ale i

výpočetní složitost nelze omezit

strukturovaným algoritmem, který by

obsahoval konečné množství cyklů for a

žádné cykly while nebo do-while

Počet volání A(m, n) – fn ~ 4n

Page 25: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Nerekurzivní výpočet

Ackermannovy funkce

Pole S … zásobník, k … index vrcholu

Page 26: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Nerekurzivní výpočet

Ackermannovy funkcePříklad: A(1, 1)

Krok … odkaz na číslo kroku algoritmu

Krok zásobník k

1 1 1 1

5 0 1 0 2

4 0 0 1 2

3 0 2 1

3 3 0

6 Konec – výsledek je 3

Page 27: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Syntaktická analýza

Definice programovacího jazyka přirozeně rekurzivní

Terminální symbol lze opsat do programu

Neterminální symbol musí být dále definován pomocí terminálních symbolů

Jednou z běžných metod překladu tzv. rekurzivní sestup

Definice jazyka obvykle začíná definicí programu, ten je definován neterminálními symboly nižší úrovně atd.

Page 28: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Příklad: aritmetické výrazy

Page 29: 4Rekurze - cvut.cz · Příklad Rekurzivní zpracování binárního stromu (přímé) 1. Je-li strom prázdný, skončíme 2. Jinak zpracujeme údaj v kořeni Rekurze Obecný tvar

Příklady – zdrojové kódy

Příklady ke stažení ke skriptu Základy

algoritmizace v C++

https://people.fjfi.cvut.cz/viriumir/, odkaz

ZALG (C++) vpravo dole

– Rekurzivní a nerekurzivní výpočet

Ackermannovy funkce: adresář

Programy\04\Ackermann

– Kalkulačka: adresář Programy\04, soubor

Kalkul.cpp


Recommended