Rekurze a zásobník. Jak se vypočítá rekurzivní program? volání metody. vyšší adresy. main(){... fa(); //push ret1... } ret1

Podobné dokumenty
5 Rekurze a zásobník. Rekurzivní volání metody

Prioritní fronta, halda (heap), řazení

Algoritmy a datové struktury

Stromy. Příklady. Rekurzivní datové struktury. Základní pojmy

Stromy. Strom: souvislý graf bez kružnic využití: počítačová grafika seznam objektů efektivní vyhledávání výpočetní stromy rozhodovací stromy

ALGORITMIZACE 2010/03 STROMY, BINÁRNÍ STROMY VZTAH STROMŮ A REKURZE ZÁSOBNÍK IMPLEMENTUJE REKURZI PROHLEDÁVÁNÍ S NÁVRATEM (BACKTRACK)

Datové struktury. alg12 1

ABSTRAKTNÍ DATOVÉ TYPY (ADT)

ALGORITMIZACE 2010/03 STROMY, BINÁRNÍ STROMY VZTAH STROMŮ A REKURZE ZÁSOBNÍK IMPLEMENTUJE REKURZI PROHLEDÁVÁNÍ S NÁVRATEM (BACKTRACK)

Stromy. Karel Richta a kol. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze Karel Richta a kol.

Základy algoritmizace c2005, 2007 Michal Krátký, Jiří Dvorský1/39

Volné stromy. Úvod do programování. Kořenové stromy a seřazené stromy. Volné stromy

Programování v C++ 1, 16. cvičení

součet cvičení celkem. známka. Úloha č.: max. bodů: skut. bodů:

Dynamicky vázané metody. Pozdní vazba, virtuální metody

Programování 3. hodina. RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015

Abstraktní datové typy: zásobník

Reprezentace aritmetického výrazu - binární strom reprezentující aritmetický výraz

Datové struktury. Obsah přednášky: Definice pojmů. Abstraktní datové typy a jejich implementace. Algoritmizace (Y36ALG), Šumperk - 12.

Vypracované okruhy z PPA2 2008

Základní datové struktury III: Stromy, haldy

Základní pojmy. Úvod do programování. Základní pojmy. Zápis algoritmu. Výraz. Základní pojmy

1. Převeďte dané číslo do dvojkové, osmičkové a šestnáctkové soustavy: a) b)

Rekurzivní algoritmy

Dynamické datové struktury IV.

Dynamické datové struktury III.

Řazení. Uspořádat množinu prvků obsahujících klíč podle definovaného kriteria.

Stromy, haldy, prioritní fronty

Stromy. Jan Hnilica Počítačové modelování 14

Dynamické datové struktury II.

ÚVODNÍ ZNALOSTI. datové struktury. správnost programů. analýza algoritmů

STACK

Spojové struktury. Spojová struktura (linked structure):

Konstruktory a destruktory

Fronta (Queue) Úvod do programování. Fronta implementace. Fronta implementace pomocí pole 1/4. Fronta implementace pomocí pole 3/4

DobSort. Úvod do programování. DobSort Implementace 1/3. DobSort Implementace 2/3. DobSort - Příklad. DobSort Implementace 3/3

Dynamické datové struktury I.

Úvod do programování - Java. Cvičení č.4

Algoritmizace a programování

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

2 Datové struktury. Pole Seznam Zásobník Fronty FIFO Haldy a prioritní fronty Stromy Hash tabulky Slovníky

Řídicí struktury. alg3 1

Algoritmizace prostorových úloh

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 21.

Implementace LL(1) překladů

Kolekce, cyklus foreach

ADT Seznam. dynamická množina. prvky vkládáme a vyjímáme na libovolné pozici (místě) v jejich posloupnosti (sekvenci) zásobník a fronta vs.

Algoritmizace prostorových úloh

Test prvočíselnosti. Úkol: otestovat dané číslo N, zda je prvočíslem

V případě jazyka Java bychom abstraktní datový typ Time reprezentující čas mohli definovat pomocí třídy takto:

IAJCE Přednáška č. 8. double tprumer = (t1 + t2 + t3 + t4 + t5 + t6 + t7) / 7; Console.Write("\nPrumerna teplota je {0}", tprumer);

Časová složitost algoritmů

B3B33ALP - Algoritmy a programování - Zkouška z předmětu B3B33ALP. Marek Boháč bohacm11

Red Black strom (Red Black Tree) Úvod do programování. Rotace. Red Black strom. Rotace. Rotace

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

B3B33ALP - Algoritmy a programování - Zkouška z předmětu B3B33ALP. Marek Boháč bohacm11

STROMOVE ALGORITMY Prohledavani do sirky (level-order) Po vodorovnejch carach fronta

int t1, t2, t3, t4, t5, t6, t7, prumer; t1=sys.readint();... t7=sys.readint(); prume pru r = r = ( 1+t 1+t t3+ t3+ t4 t5+ t5+ +t7 +t7 )/ ;

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Stromy. Jan Kybic.

BINARY SEARCH TREE

1. Téma 12 - Textové soubory a výjimky

Úvod do programovacích jazyků (Java)

Rozklad problému na podproblémy

4. Rekurze. BI-EP1 Efektivní programování Martin Kačer

ADT STROM Lukáš Foldýna

3. přednáška. Obsah: Řídící struktury sekvence, if-else, switch, for, while, do-while. Zpracování posloupnosti

Úvod do programovacích jazyků (Java)

Středoškolská technika 2017 PROGRAM NA GENEROVÁNÍ PRVOČÍSEL

Dynamické programování. Optimální binární vyhledávací strom

Binární vyhledávací stromy pokročilé partie

ALG 04. Zásobník Fronta Operace Enqueue, Dequeue, Front, Empty... Cyklická implementace fronty. Průchod stromem do šířky

Struktura programu v době běhu

Paměť počítače. alg2 1

KTE / ZPE Informační technologie

Datový typ prioritní fronta Semestrální práce z předmětu 36PT

Abstraktní datové typy

VYSOKÉ UČENÍ TECHNICKÉ V BRNĚ

Výčtový typ strana 67

Implementace binárního stromu směrníky

Aplikovaná informatika. Podklady předmětu Aplikovaná informatika pro akademický rok 2013/2014 Radim Farana. Obsah. Strom

Základy algoritmizace. Hašování

bin arn ı vyhled av an ı a bst Karel Hor ak, Petr Ryˇsav y 23. bˇrezna 2016 Katedra poˇ c ıtaˇ c u, FEL, ˇ CVUT

ADT/ADS = abstraktní datové typy / struktury

BINARY SEARCH TREE

Správa paměti. Karel Richta a kol. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze Karel Richta, 2016

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 12.

Pascal. Katedra aplikované kybernetiky. Ing. Miroslav Vavroušek. Verze 7

Seznamy a iterátory. Kolekce obecně. Rozhraní kolekce. Procházení kolekcí

a) b) c) Radek Mařík

TGH07 - Chytré stromové datové struktury

Intervalové stromy. Představme si, že máme posloupnost celých čísel p 0, p 1,... p N 1, se kterou budeme. 1. Změna jednoho čísla v posloupnosti.

Binární vyhledávací strom pomocí směrníků Miroslav Hostaša L06620

Vyvažování a rotace v BVS, všude se předpokládá AVL strom

Z. Kotala, P. Toman: Java ( Obsah )

ABSTRAKTNÍ DATOVÉ TYPY

Datové struktury obsah přednášky 1. Úvod 2. Třídy Type-wrapper (obalový typ) pro primitivní typy automatické převody 3. Automatické převody mezi

Adresní vyhledávání (přímý přístup, zřetězené a otevřené rozptylování, rozptylovací funkce)

5. přednáška - Rozklad problému na podproblémy

Časová a prostorová složitost algoritmů

Transkript:

Rekurze a zásobník Jak se vypočítá rekurzivní program? volání metody vyšší adresy ret1 main(){... fa(); //push ret1... PC ret2 void fa(){... fb(); //push ret2... return //pop void fb(){... return //pop ret1 ret2 SP nižší adresy

Rekurzivní volání metody volání rekurzivní metody z metody main() vstup do metody nula nebo více rekurzivních volání dosažení základního případu a následné výstupy z rekurzivních volání až po návrat do metody main()

class Faktorial { public static void main (String[] args) { int n = Integer.parseInt(args[0]); System.out.println(n+"! = "+f(n)); // volání // rekurzivní metody f, uložení do zásobníku // parametru n a adresy pro návrat static int f(int n) { if (n > 1) // vstup, rozhodnutí nastal-li // základní případ return n * f(--n); // rekurzivní volání, // do zásobníku vložíme parametr // n-1 a adresu násobení else return 1;// jsme na základním případu a // vykonáme výstup, přičemž podle // adresy v záznamu na vrcholu // zásobníku pokračujeme násobením // nebo návratem do metody main()

Eliminace rekurze uživatelským zásobníkem Aktivační záznam par - parametr pro faktoriál segmentkodu - indikace pokračování výpočtu s hodnotami návrat - skončení rekurze násobení - výpočet faktoriálu při výstupu z rekurzivního volání class AZaznam { int par; int segmentkodu; AZaznam(int parametr, int segment) { par = parametr; segmentkodu = segment; vstup do rekurzivní metody zjišťuje hodnotu parametru - if (n > 1)... čtení prvku na vrcholu zásobníku (ne pop) - top

class AZasobnik { private AZaznam[] z; private int vrchol; final int maxn=10; AZasobnik() { z = new AZaznam[maxN]; vrchol = -1; void push(azaznam ref) { z[++vrchol] = ref; AZaznam pop() { return z[vrchol--]; AZaznam top() { return z[vrchol];

Schéma výpočtu programu Faktorial 1:volání PUSH(n,návrat) 2:vstup TOP par? výsledek=1 3:rekurzivní volání PUSH(par-1, násobení) 5:výstup POP segmentkodu? 6:návrat výsledek n! 4:násobení TOP výsledek= výsledek*par

class ZFaktorial { static int n; static int vysledek; static AZasobnik azasob; static int segment; static AZaznam azaz; public static void main(string[] args) { n=7; faktorial(); System.out.println(n + "! = " + vysledek); static void faktorial() { azasob = new AZasobnik(); segment = 1; while (pokracuj()) ;

static boolean pokracuj() { switch(segment) { case 1: // volání azaz = new AZaznam(n,6); azasob.push(azaz); segment = 2; break; case 2: // vstup azaz = azasob.top(); if(azaz.par > 1) segment = 3; else { vyslede k = 1; segment = 5; break; case 3: // rekurzivní volání AZaznam novyzaznam = new AZaznam(azaz.par - 1, 4) ; azasob.push(novyzaznam); segment = 2; break; case 4: // násobení azaz = azasob.top(); vysledek = vysledek * azaz.par; segment = 5; break; case 5: // výstup azaz = azasob.pop(); segment = azaz.segment Kodu; break; case 6: // návrat return false; return true;

program je možné dále upravit Výpočet 0! // hodnoty na začátku případů, větve volani: vstup: vysledek= vysledek= Z: ( ) Z: ( [0,navrat] ) vystup: vysledek=1 Z: ( [0,navrat] ) navrat: vysledek=1 Z: ( ) Výpočet 2! volani: vstup: vysledek= vysledek= Z:( ) Z:( [2,navrat] ) rekurzivni volan i: vysledek= Z:( [2,navrat] ) vstup: vysledek= Z:( [2,navrat] [1,nasobeni] ) vystup: vysledek=1 Z:( [2,navrat] [1,nasobeni] ) nasobeni: vysledek=1 Z:( [2,navrat]) vystup: vysledek=2 Z:( [2,navrat] ) navrat: vysledek=2 Z:( )

ADT Strom (tree) Příklady - - rodokmen (family tree) vylučovací systém soutěží (turnaj) - aritmetický výraz

Organizace knížky Herout P.: Učebnice jazyka Java Obsah Úvod 2 Základní pojmy 20 Vlákna Literatura Rejstřík 2.1 Trocha historie nikoho nezabije 2.6 Co byste měli vědět, než začnete programovat 2.6.1 Jak přeložit a spustit program 2.6.2 Běžné problémy - systém souborů

Základní pojmy vrchol - prvek ADT strom hrana - spojení dvou vrcholů Strom a) Jeden vrchol je strom. Tento vrchol se nazývá kořen stromu. b) Nechť x je vrchol a T1, T2,..., Tn jsou stromy. Strom je vrchol x spojený s kořeny stromů T1, T2,..., Tn a x je kořenem. T1, T2,..., Tn - podstromy kořeny T1, T2,..., Tn následníci (synové) vrcholu x vrchol x - předchůdce (otec) kořenů T1, T2,..., Tn prázdná množina prvků - strom

list vrchol bez následníků vnitřní vrchol vrchol, který není listem cesta - posloupnost vrcholů, ve které po sobě jdoucí vrcholy jsou spojeny hranou délka cesty - počet hran cesty Ke každému vrcholu je z kořene právě jedna cesta. hloubka vrcholu ve stromě (úroveň, na které se nachází) - délka cesty z kořene k vrcholu Úroveň (hloubka) kořene stromu je nulová. výška stromu - maximální hloubka vrcholu stromu

Následníci můžou být uspořádani. a a b c c b Binární strom je prázdný strom anebo vrchol, který má levý a pravý podstrom, které jsou binární stromy.

Implementace polem Pozice vrcholů úplného binárního stromu lze očíslovat: kořenu přiřadíme 1 levému následníku 2 pravému následníku 3 pokračujeme na každé úrovni zleva až do konce pozice = index prvku pole je-li na ní vrchol klíč není-li např. -1 Má-li vrchol hodnotu indexu i, potom levý následník má index 2i pravý následník má index 2i + 1 předchůdce, pokud existuje, má index i/2 (celočíselně). - musíme vytvořit pole pro předpokládanou maximální velikost stromu - navíc musí obsahovat i prvky pro pozice neobsazené vrcholy Poznámka: Uvedené vztahy platí, má-li kořen stromu index 1. Pokud bychom kořen umístnili do prvku pole s indexem 0, tyto vztahy nutno upravit.

Implementace spojovou strukturou class Vrchol { int klic; Vrchol levy; Vrchol pravy;... void tiskvrcholu() { System.out.print(klic+ ); Přímý průchod (preorder) navštívíme vrchol, potom levý a pravý podstrom Vnitřní průchod (inorder) navštívíme levý podstrom, vrchol a pravý podstrom Zpětný průchod (postorder) navštívíme levý a pravý podstrom a potom vrchol

Rekurzivní průchod stromem preorder: void pruchodr(vrchol v) { if (v == null) return; v.tiskvrcholu(); pruchodr(v.levy); pruchodr(v.pravy); Vrchol koren; pruchodr (koren); inorder: posunutím řádku s tiskem mezi rekurzivní volání postorder: posunutím za obě rekurzivní Čas průchodu stromem: T(0) = c por T(n) = T(m) + T(n-m-1) + c por + c tisk pro n > 0 T(n) = (2c por + c tisk )n + c por Čas průchodu stromem je Θ(n).

Nerekurzivní implementace průchodů 1. Do zásobníku vložíme procházený strom 2. Dokud zásobník není prázdný, v cyklu vybereme prvek ze zásobníku a je-li ním klíč vytiskneme ho, jinak do zásobníku vložíme pro preorder: pravý podstrom, levý podstrom, klíč vrcholu pro inorder: pravý podstrom, klíč vrcholu, levý podstrom pro postorder: klíč vrcholu, pravý podstrom, levý podstrom Nerekurzivní preorder Pro preorder průchod je při vkládání jako poslední vložen klíč a ten je tedy na začátku uvedeného cyklu vybrán a vytisknut. void pruchod(vrchol v) { VZasobnik z = new VZasobnik(); z.push(v); while (!z.jeprazdny()) { v = z.pop(); v.tiskvrcholu( ); if (v.pravy!= null) z.push(v.pravy); if (v.levy!= null) z.push(v.levy);

Průchod po úrovních (level order) void pruchod(vrchol v) { VFronta f = new VFronta( ); f.vloz(v); while (!f.jeprazdna()) { v = f.vyber (); v.tiskvrcholu(); if (v.levy!= null) f.vloz(v.levy); if (v.pravy!= null) f.vloz(v.pravy);

Binární vyhledávací stromy (BVS) uspořádaná množina vyhledání vložení implementace polem O(log n) O(n) implementace seznamem O(n) O(n) Je lepší implementace? Prvky ve vrcholech BVS splňují BVS vlastnost: Nechť x je vrchol stromu. Je-li y vrchol v levém podstromu, potom y.klíč < x.klíč. Je-li y vrchol v pravém podstromu, potom y.klíč > x.klíč. ( klíče všech prvků jsou různé)

vyhledání dat uložených ve vrcholu private class DVrchol { int klic; String data; DVrchol levy; DVrchol pravy; DVrchol (int klic, String data) { this.klic = klic; this.data = data; void tiskvrcholu() { System.out.print(data+ ); BVS strom private DVrchol koren; prázdný strom koren == null

signatura metody hledej String hledej(int) rekurzivní implementace private String hledejr(dvrchol v, int klic) { if (v == null) return null; if (klic == v.klic) return v.data; if (klic < v.klic) return hledejr(v.levy, klic); else return hledejr(v.pravy, klic); String hledej(int klic) { return hledejr(koren, klic); odstranění koncové rekurze String hledej(int klic) { DVrchol x = koren; while (x!= null && klic!= x.klic) if (klic < x.klic ) x = x.levy; else x = x.pravy; return x == null? null : x.data;

nalezení minimálního a maximálního prvku (neprázdného BVS) int minklic() { DVrchol x = koren; while (x.levy!= null) x = x.levy; return x.klic; int maxklic() { DVrchol x = koren; while (x.pravy!= null) x = x.pravy; return x.klic;

vložení a výběr prvku predch - ukazatel na předchůdce private class DVrchol { int klic; String data; DVrchol levy; DVrchol pravy; DVrchol predch; DVrchol (int klic, String data) { this.klic = klic; this.data = data; void tiskvrcholu() { System.out.print(data+" ");

signatura metody vloz void vloz(int, String) void vloz(int klic, String data) { DVrchol x = koren, predch = null; while (x!= null ) { predch = x; if (klic < x.klic) x = x.levy; else x = x.pravy; DVrchol z = new DVrchol(klic, data); z.predch = predch; if (predch == null) koren = z; else if (klic < predch.klic) predch.levy = z; else predch.pravy = z; Průchod inorder BVS vytiskne tyto prvky uspořádané vzestupně podle klíče.

výběr prvku list

výběr prvku vnitřní prvek s jedním následníkem

výběr prvku vnitřní prvek se dvěma másledníky

signatura metody vyber void vyber(int) void vyber(int klic) { // najdeme vrchol z na vylouceni DVrchol z = koren; while (z!= null && klic!= z.klic) if (klic < z.klic ) z = z.levy; else z = z.pravy; // urcime vrchol y na odstraneni DVrchol y = z; if (z.levy!= null && z.pravy!= null) { y = z.pravy; while (y.levy!= null) y = y.levy; // x ukazuje na naslednika y anebo je null, // kdyz nema zadneho naslednika DVrchol x; if (y.levy!= null) x = y.levy; else x = y.pravy; // modifikaci y. predch a x odpojime y if (x!= null) x.predch = y.predch; if (y.predch == null) koren = x; else if (y == y.predch.levy) y.predch.levy = x; else y.predch.pravy = x;

// nebyl-li odpojen z, skopirujeme klic a // data if (y!= z) { z.klic = y.klic; z.data = y.data; // uvolnime y y = null;

Vlastnosti BVS h výška BVS složitost hledání a vkládání je O(h) N počet prvků (vrcholů) nejhorší případ: h = N 1 složitost je O(N) nejlepší případ: kromě poslední úrovně, jsou zaplněny všechny vyšší úrovně h = log 2 N složitost je O(log N) h h+1 2 N < 2

obecně: průměrná hloubka vrcholu hledaného/vkládaného součet délek cest k vrcholúm BVS / N kořen BVS - i-tý největší prvek i-tý největší prvek, i-1 vrcholů N-i vrcholů PN - průměrný součet délek cest BVS s N vrcholy P N = 1 N ( P i-1 + i 1 + P N-i + N i) 1 i N PN 2N ln N = 1,39N log 2 N průměrný hloubka vrcholu pro průměrný případ: P N / N složitost je O(log N)

Poznámky: Výběr prvku lze učinit několika způsoby, vedou však k tomu, že strom po odstranění nezůstává náhodným, někdy se průměrná hloubka změní na N. Možným řešením je označit vybraný prvek jako neplatný, například použitím logické členské proměnné. Často v aplikaci nemáme mnoho vybraných prvků a dokonce můžou být užitečné pokud by jich bylo později opět potřeba. Další technikou je vytvoření nového stromu pro platné prvky, dosáhl- li počet neplatných vrcholů nějakou mez, co je také častý způsob práce s datovými strukturami. Vyvážené stromy nejhorší případ operací je O(log N). (cesta z kořene ke každému listu není o moc delší než k ostatním) http://java.sun.com/j2se/1.5.0/docs/api/java/util/treemap.html

Odpovídá každé permutaci N prvků různý BVS? Uložme prvky posloupnosti do mřížky tak, že řádek odpovídá hodnotě a sloupec poloze Příklad 3,5,2,4,1 x x x x 1 x x 2 x x 3 x x x x x x x 4 x x 5 x x x - mřížková reprezentace BVS Výměnou sloupců odpovídajících vrcholům nad a pod libovolným vrcholem se vyhledávací strom nezmění, posloupnost ano. 3,5,2,1,4 x x x 1 x x x 2 x x 3 x x x x x x x x 4 x 5 x x x Počet všech posloupností z N prvků je N! Počet různých binárních stromů s N vrcholy je ~ 4 N / (πn)