Rekurze
This presentation is the property of its rightful owner.
Sponsored Links
1 / 64

Rekurze PowerPoint PPT Presentation


  • 110 Views
  • Uploaded on
  • Presentation posted in: General

Rekurze. Rekurze. volání podprogramu opětovně v jeho těle v době, kdy předchozí volání ještě nebylo ukončeno Druhy rekurze přímá rekurze nepřímá rekurze. Přímá rekurze. podprogram volá sám sebe void A(…) { A(); }. Nepřímá rekurze. aktivují se vzájemně dva podprogramy void A(…)

Download Presentation

Rekurze

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Rekurze

Rekurze


Rekurze1

Rekurze

  • volání podprogramu opětovně v jeho těle

    • v době, kdy předchozí volání ještě nebylo ukončeno

      Druhy rekurze

  • přímá rekurze

  • nepřímá rekurze


P m rekurze

Přímá rekurze

  • podprogram volá sám sebe

    void A(…)

    {

    A();

    }


Nep m rekurze

Nepřímá rekurze

  • aktivují se vzájemně dva podprogramy

    void A(…)

    {

    B();

    }

    void B(…)

    {

    A();

    }


Rekurze

  • pravidla tvorby rekurzivní funkce

    • musí být definována podmínka pro ukončení rekurze

      • v algoritmu se musí ověřit, zda nenastala koncová situace

    • v každém kroku musí dojít ke zjednodušení problému


P klad 1

Příklad 1

Napište rekurzivní funkci pro výpočet faktoriálu

long fakt(int n)

{

if (n<=1) return 1;

else

returnn*fakt(n-1);

}


Jak se rekurze vol

Jak se rekurze volá?

int main()

{

fakt(2);

}

fakt(2)

2

return 2*fakt(1)

1

return 1


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2584

a

4589

Zásobník

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2584

a

4589

Zásobník

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2584

a

4589

Zásobník

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2584

a

4589

Zásobník

n

2

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2584

a

4589

Zásobník

5

n

2

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2584

a

4589

Zásobník

x

123464545

5

n

2

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2584

a

4589

Zásobník

x

123464545

5

n

2

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2584

a

4589

Zásobník

n

1

x

123464545

5

n

2

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2584

a

4589

Zásobník

x

123664545

5

n

1

x

123464545

5

n

2

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2584

a

4589

Zásobník

x

123664545

5

n

1

x

123464545

5

n

2

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

1

a

4589

Zásobník

5

n

1

x

123464545

5

n

2

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

1

a

4589

Zásobník

n

1

x

1

5

n

2

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

1

a

4589

Zásobník

x

1

5

n

2

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2584

a

4589

Zásobník

x

2

5

n

2

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2

a

4589

Zásobník

5

n

2

x

12346786

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2

a

4589

Zásobník

n

2

x

2

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2

a

4589

Zásobník

x

2

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

2

a

4589

Zásobník

x

6

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

6

a

4589

Zásobník

11

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

6

a

6

Zásobník

n

3


Rekurze

V registru procesoru AX se předává návratová hodnota

long fakt(int n)

{long x;

1:if (n<=1)

2: return 1;

3:else

{

4:x=fakt(n-1);

5:x = n*x;

6: return x;

}

}

int main()

{long a;

10: a = fakt(3);

11: cout << a; }

AX:

6

a

6

Zásobník


Loha 1

Úloha 1

Napište rekurzivní funkci pro výpočet Fibbonaciho posloupnosti

F(0) = 0

F(1) = 1

F(n) = F(n-1) + F(n-2)


Rekurze

  • rekurze, je-li příliš „hluboká“, způsobí růst velikosti zásobníku

    • v některých případech je možné ji nahradit pouhým cyklem

    • jindy se musí simulovat zásobník

      long fakt(int n)

      {

      long faktorial = 1;

      for(i=2;i<=n;i=i+1)

      faktorial = faktorial*i;

      return faktorial;

      }


Loha 2

Úloha 2

  • Je dána celá částka v Kč. Máme k dispozici mince v hodnotách 20 Kč, 10 Kč, 5 Kč, 2Kč, 1 Kč. Napište rekurzivní proceduru, která vytiskne na obrazovku složení částky z co nejmenšího počtu mincí (vytiskne seznam mincí).

  • Domácí úloha: Odstraňte rekurzi (přepište proceduru pomocí cyklu).


Hanojsk v e

Hanojské věže

  • máme 3 tyče (1, 2, 3)

  • na první tyči je věž z n disků naskládaných na sebe, spodní disk má největší průměr

  • úkol:

    • přemístit věž z tyče 1 na tyč 2 pomocí třetí tyče 3 přesouváním disků za podmínek:

      • v jediném kroku lze přenést jeden disk z tyče na tyč

      • disk lze odložit pouze na tyč

      • nelze položit disk o větším průměru na disk s menším průměrem.


Rekurze

  • triviální úloha

    • přenesení věže o výšce 1, tj. přenesení disku, z tyče na tyč

    • je reprezentována procedurou

      void Prenes_disk(int odkud, int kam),

      která v našem programu vypíše informaci o přesunu disku, např.: 1 -> 2

  • úvaha

    • chci-li přesunout věž např. o výšce 3 disky z tyče 1 na tyč 2 pomocí tyče 3, musím nejprve přesunout věž o výšce 2 (počítáno od shora) na tyč 3 pomocí 2, pak přesunout spodní největší disk z tyče 1 na tyč 2 a nakonec přesunout věž o výšce 2 z tyče 3 na tyč 2 pomocí tyče 1


Rekurze

odkud = tyč 1

kam = tyč 2

pomocí = tyč 3


Rekurze

void prenes_vez(int vyska, int odkud, int kam, int pomoci)

{

if (vyska == 1) prenes_disk(odkud,kam);

else

{

prenes_vez(vyska-1, odkud, pomoci, kam);

prenes_disk(odkud,kam);

prenes_vez(vyska-1,pomoci,kam,odkud);

}

}


Jak je slo itost algoritmu

Jaká je složitost algoritmu?

  • přesunutí věže o n discích se skládá z přesunutí věže o (n-1) discích, přesunutí disku a přesunutí věže zpět o (n-1) discích

  • počet kroků algoritmu (počet přesunutí disků) je dán rekurentním vztahem:

    F(n) = F(n-1) + 1 + F(n-1) = 2F(n-1)+1,

    přičemž F(1) = 1


Rekurze

  • řešením rovnice je vztah

    F(n) = 2n - 1

    tj. počet přesunů disku u věže výšky n je roven 2n - 1

  • složitost algoritmu je tedy O(2n)

    exponenciální


Aplikace rekurze

Aplikace rekurze

Prohledávání s návratem (Backtracking)

  • používá se pro hledání všech řešení daného problému

  • princip:

    • řešení hledám po krocích, pokud je řešení nalezeno nebo nelze úlohu dále řešit, vrátím se o krok zpět

  • úlohy:

    • hledání všech cest v bludišti

    • problém rozmístění 8 dam na šachovnici


Probl m 8 dam na achovnici

Problém 8 dam na šachovnici

  • úkol:

    • umístit 8 dam na šachovnici 8x8 polí, aby se vzájemně neohrožovaly

  • princip:

    • umístím dámu na první řádek na první sloupec, další dámu na druhý řádek na třetí sloupec atd., pokud nemohu další dámu umístit, provedu návrat na předchozí řádek a dámu posunu


Probl m 8 dam

Problém 8 dam

  • demonstrace na 4 dámách na šachovnici 4x4


Probl m 8 dam1

Problém 8 dam


Probl m 8 dam2

Problém 8 dam

další dámu nemohu umístit, provedu návrat


Probl m 8 dam3

Problém 8 dam


Probl m 8 dam4

Problém 8 dam


Probl m 8 dam5

Problém 8 dam

další dámu nemohu umístit, provedu návrat


Probl m 8 dam6

Problém 8 dam


Probl m 8 dam7

Problém 8 dam


Probl m 8 dam8

Problém 8 dam


Probl m 8 dam9

Problém 8 dam


Probl m 8 dam10

Problém 8 dam


Probl m 8 dam11

Problém 8 dam


Rekurze

Rozděl a panuj (Divide and Conquer)

  • používá se pro zjednodušení řešení složitého problému

  • princip:

    • rozdělím prostor řešení na dva menší (pokud možno stejně velké) podprostory

    • vyřeším problém na každém podprostoru samostatně (stejnou technikou)

    • spojím obě řešení

  • úlohy:

    • Hanojské věže

    • řazení: QuickSort


Hled n cest v bludi ti

Hledání cest v bludišti


Rekurze

  • algoritmus s návratem (rekurzivní)

    • je-li to možné, v každé místnosti zkusím „jít na všechny“ světové strany do další místnosti

    • pokud jsem našel východ, vypíši cestu a vrátím se o krok zpět

    • vracím se o krok zpět, nemohu-li postoupit do další mísnosti (jsem v slepé uličče)


Rekurze

Jak bude principiálně algoritmus vypadat?

Napišme jej v pseudokódu.

  • Připomeňme si pravidla tvorby rekurzivní procedury:

  • podmínka ukončení rekurze

    • nalezení východu nebo slepá ulička

  • zjednodušení problému v dalším kroku

    • postoupil jsem do další místnosti (nalezená cesta je o 1 krok delší)


Rekurze

jdi_do_mistnosti(kam)

{

if (jsem_venku) { tiskni_cestu(); return;}

else

{

if (mohu_na_sever) jdi_do_mistnosti(sever);

if (mohu_na_jih) jdi_do_mistnosti(jih);

if (mohu_na_vychod) jdi_do_mistnosti(vychod);

if (mohu_na_zapad) jdi_do_mistnosti(zapad);

}

}


Rekurze

Donald Knuth

Data + Algorithms = Programs

Rozmyslíme si datové struktury a

algoritmy nad nimi !


Rekurze

  • reprezentace bludiště

    • informace o velikosti – šířce a délce

    • dynamické dvourozměrné pole informací o místnostech

  • typedef struct

  • {

  • int sirka, delka;

  • TMistnost **plocha;

  • } TBludiste;


Rekurze

  • reprezentace místnosti

    • informace o otevřenosti dveří na čtyři světové strany

  • typedef enum { ZAVRENO=0,OTEVRENO=1} TStavDveri;

  • typedef struct

  • {

  • TStavDveri sever;

  • TStavDveri jih;

  • atd;

  • } TMistnost;


Rekurze

  • kam budu ukládat místnosti z nalezené cesty

    • nevím předem, jak bude cesta dlouhá

    • mám algoritmus s návratem, tj. při postupu do jiné místnosti potřebuji přidávat na konec cesty novou mísnost, při návratu ji z konce odebrat

    • nejlepší bude obousměrný spojový seznam

  • prevence proti cyklu

    • booleovké pole místností, které jsem navštívil

    • mohu doplnit o přímý test, abych nešel na tu světovou stranu v místnosti, ze které jsem přišel


Rekurze

  • hlavička rekurzivní procedury

    void jdi_do_mistnosti(TBLudiste &bludiste,

    TSvetStrany kam_jdu,

    int x, int y,

    TCesta &cesta);


Rekurze

Úloha

Vstupem programu jsou čísla N a K. Nalezněte všechny K-tice celých kladných čísel x1,x2,x3, … x(K-1), xK, pro které platí

x1 <= x2 <= x3 <=…<= x(K-1) <=xK a

x1 + x2 + x3 +…..+ x(K-1) + xK = N.


Rekurze

Úloha

Kostka domina je tvořena dvěma poli. Každé z nich může být prázdné nebo může obsahovat jistý počet teček od 1 do 6. Kostky se skládají do řady tak, že vedle sebe stojící kostky musí sousedit stejnými poli.

Vstupem vašeho programu bude soubor se seznamem kostek domina, které máte k dispozici (na každém řádku bude dvojice čísel oddělená mezerou, představující počet teček). V seznamu se může opakovat i více stejných kostek. Zjistěte jakou nejdelší řadu lze z těchto kostek sestavit. Vytiskněte tuto řadu a její délku měřenou počtem kostek. Stačí jedno řešení.


  • Login