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

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

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

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

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

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

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

Algoritmy a datové struktury

Rekurzivní algoritmy

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

Rozptylování, stromy - zákl. vlastnosti

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

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

BINARY SEARCH TREE

Dynamické datové struktury II.

RECURSION

BINARY SEARCH TREE

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

R zné algoritmy mají r znou složitost

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

Stromy, haldy, prioritní fronty

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

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

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

Stromy. Jan Kybic.

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

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

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

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

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

Dynamické datové struktury IV.

bfs, dfs, fronta, zásobník, prioritní fronta, halda

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

Dynamické struktury a Abstraktní Datový Typy (ADT)

PŘETĚŽOVÁNÍ OPERÁTORŮ

Část 1 Spojové struktury (stromy) Dynamické struktury a Abstraktní Datový Typy (ADT) Část 2 Abstraktní datový typ. Část 3 Příklad ADT Prioritní fronta

bfs, dfs, fronta, zásobník, prioritní fronta, halda

STACK

Abstraktní datové typy

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.

prohled av an ı graf u Karel Hor ak, Petr Ryˇsav y 16. bˇrezna 2016 Katedra poˇ c ıtaˇ c u, FEL, ˇ CVUT

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

Stromy. Jan Faigl. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze. Přednáška 10 B0B36PRP Procedurální programování

pak celou úlohu. ani Jako obvykle je static int M, N; [] key, L, R; NIL = -1; cost; roota, rootb; throws IOExceptio // tree roots on { static void

Programování v C++ 2, 4. cvičení

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

Dynamické datové struktury III.

Stromy. Jan Faigl. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze. Přednáška 10 B0B36PRP Procedurální programování

2. Mřížky / Záplavové vyplňování

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

Část 2 Příklad načítání grafu, kompilace a projekt s více soubory. Část 3 Zadání 9. domácího úkolu (HW09)

Datové struktury Úvod

Dynamické programování

Abstraktní datové typy: zásobník

Binární vyhledávací stromy II

Dynamické datové struktury I.

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

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

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

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

TGH07 - Chytré stromové datové struktury

Konstruktory a destruktory

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

TGH07 - Chytré stromové datové struktury

IB108 Sada 1, Příklad 1 Vypracovali: Tomáš Krajča (255676), Martin Milata (256615)

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ů

Protože pi každém volání funkce ff se zavolá funkce abc() práv jednou, je poet volání funkce abc() práv 7. Platí varianta d).

Kolekce, cyklus foreach

Zdůvodněte, proč funkce n lg(n) roste alespoň stejně rychle nebo rychleji než než funkce lg(n!). Symbolem lg značíme logaritmus o základu 2.

Datové struktury. alg12 1

6. Tahy / Kostry / Nejkratší cesty

DSA, První krok: máme dokázat, že pro left = right vrátí volání f(array, elem, left, right)

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

STACK

VYSOKÉ UČENÍ TECHNICKÉ V BRNĚ

Programovanie v jazyku C stromy

Základní datové struktury

a) b) c) Radek Mařík

Algoritmizace a programování

Algoritmizace prostorových úloh

STROMY A KOSTRY. Doc. RNDr. Josef Kolář, CSc. Katedra teoretické informatiky, FIT České vysoké učení technické v Praze. BI-GRA, LS 2010/2011, Lekce 6

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

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

A4B33ALG 2010/05 ALG 07. Selection sort (Select sort) Insertion sort (Insert sort) Bubble sort deprecated. Quicksort.

Dynamic programming. Optimal binary search tree

Jméno:... St. Sk.:. Cvičící:.. Bodů ze cv.: (Tučná čísla indikují počet neuspěvších (z 50) v jednotlivých otázkách) 1.

Select sort: krok 1: krok 2: krok 3: atd. celkem porovnání. výběr nejmenšího klíče z n prvků vyžaduje 1 porovnání

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

Reprezentace dat v informačních systémech. Jaroslav Šmarda

Lineární datové struktury

STROMY A KOSTRY. Stromy a kostry TI 6.1

9. lekce Úvod do jazyka C 4. část Funkce, rekurze Editace, kompilace, spuštění Miroslav Jílek

Prioritní fronta a příklad použití v úloze hledání nejkratších cest

Algoritmizace prostorových úloh

Zápis programu v jazyce C#

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

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

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

Řešení: PŘENESVĚŽ (N, A, B, C) = přenes N disků z A na B pomocí C

Část I. Část 1 Prioritní fronta (Halda) Přehled témat. Prioritní fronta a příklad použití v úloze hledání nejkratších cest

Transkript:

ALGORITMIZACE 2010/03 STROMY, BINÁRNÍ STROMY VZTAH STROMŮ A REKURZE ZÁSOBNÍK IMPLEMENTUJE REKURZI PROHLEDÁVÁNÍ S NÁVRATEM (BACKTRACK) Strom / tree uzel, vrchol / node, vertex hrana / edge vnitřní uzel / internal node list / leaf (pl. leaves) 1

Příklady stromů b) c) d) a) e) Vlastnosti stromů 1. Strom je souvislý, tj. mezi každými dvěma jeho uzly vede cesta. 2. Mezi každými dvěma uzly ve stromu vede jen jediná cesta. 3. Po odstranění libovolné hrany se strom rozpadá na dvě části. 4. Počet hran ve stromu je vždy o 1 menší než počet uzlů. 2

Kořenový strom / rooted tree h k j g m i a l b R n f c d e Kořen / root a m j i k l h g R b n e c d f Názvosloví j i Předchůdce, rodič / predecessor, parent Následník, potomek / successor, child 3

Hloubka / depth R 0 a b c 1 m j i n d 2 k l h e f 3 g 4 4 Hloubka uzlu / Hloubka stromu / node depth tree depth 4

Binární (kořenový!!) strom / binary (rooted!!) tree Počet potomků každého uzlu je 0,1, nebo 2. Levý a pravý podstrom / left and right subtree x Podstrom uzlu x... levý... pravý 5

Pravidelný binární strom / regular binary tree Počet potomků každého uzlu je jen 0 nebo 2. Vyvážený strom / balanced tree Hloubky všech listů jsou (víceméně) stejné. 6

Hloubka vyváženého (binárního a pravidelného!) stromu hloubka 0 1 2 3 4 uzlů 1 2 4 8 16 k 2 k 2 k+1-1 (2 (hloubka vyváženého stromu)+1 1) ~ uzlů hloubka vyváženého stromu ~ log 2 (uzlů+1) 1 ~ log 2 (uzlů) 7

Implementace binárního stromu -- C Strom Uzel Reprezentace uzlu left key right typedef struct node { 73501 9968 497 int key; struct node *left; struct node *right; } NODE; 8

Implementace binárního stromu -- Java Strom 6084 Uzel 335 22107 public class Node { public Node left; public Node right; public int key; public Node(int k) { key = k; left = null; right = null; } } public class Tree { public Node root; public Tree() { root = null; } } 9

Vybudování náhodného binárního stromu -- C NODE *randtree(int depth) { NODE *pnode; if ((depth <= 0) (random(10) > 7)) return (NULL); //stop recursion pnode = (NODE *) malloc(sizeof(node)); // create node if (pnode == NULL) { printf("%s", "No memory."); return NULL; } pnode->left = randtree(depth-1); // make left subtree pnode->key = random(100); // some value pnode->right = randtree(depth-1); // make right subtree return pnode; // all done } Příklad volání funkce NODE *root; root = randtree(4); Poznámka. Volání random(n) vrací náhodné celé číslo od 0 do n-1. Zde neimplementováno. 10

Vybudování náhodného binárního stromu -- Java public Node randtree(int depth) { Node node; if ((depth <= 0) ((int) Math.random()*10 > 7) return null; // create node with a key value node = new Node((int)(Math.random()*100)); } node.left = randtree(depth-1); // create left subtree node.right = randtree(depth-1); // create right subtree return node; // all done Příklad volání funkce Node root; root = randtree(4); 11

Náhodný binární strom 13 39 83 84 58 28 98 71 5 Reprezentace stromu 13 39 83 84 58 28 98 71 5 12

Průchod (binárním) stromem v pořadí Inorder 13 Strom 84 39 58 83 28 98 71 5 Průchod stromem v pořadí INORDER void listinorder( NODE *ptr) { if (ptr == NULL) return; listinorder(ptr->left); printf("%d ", ptr->key); listinorder(ptr->right); } Výstup 98 84 71 39 13 58 5 83 28 13

Pohyb ve stromu v průchodu Inorder Okamžik tisku Směr pohybu listinorder(ptr->left); printf("%d ", ptr->key); listinorder(ptr->right); A B C D E F G H I J K L M N O Výstup H D I B J E K A L F M C N G O 14

Průchod (binárním) stromem v pořadí Preorder 13 Strom 84 39 58 83 28 98 71 5 Průchod stromem v pořadí PREORDER void listpreorder( NODE *ptr) { if (ptr == NULL) return; printf("%d ", ptr->key); listpreorder(ptr->left); listpreorder(ptr->right); } Výstup 13 39 84 98 71 83 58 5 28 15

Pohyb ve stromu v průchodu Preorder Okamžik tisku Směr pohybu printf("%d ", ptr->key); listpreorder(ptr->left); listpreorder(ptr->right); A B C D E F G H I J K L M N O Výstup A B D H I E J K C F L M G N O 16

Průchod (binárním) stromem v pořadí Postorder 13 Strom 84 39 58 83 28 98 71 5 Průchod stromem v pořadí POSTORDER void listpostorder( NODE *ptr) { if (ptr == NULL) return; listpostorder(ptr->left); listpostorder(ptr->right); printf("%d ", ptr->key); } Výstup 98 71 84 39 5 58 28 83 13 17

Pohyb ve stromu v průchodu Postorder Okamžik tisku Směr pohybu listpostorder(ptr->left); listpostorder(ptr->right); printf("%d ", ptr->key); A B C D E F G H I J K L M N O Výstup H I D J K E B L M F N O G C A 18

Velikost stromu (= počet uzlů) rekurzivně Strom nebo podstrom 3 4 13 4 39 9 2 Příklad 83 1 m uzlů n uzlů 1 84 1 98 71 58 1 5 28 celkem... m+n+1 uzlů int count(node *ptr) { if (ptr == NULL) return (0); return (count(ptr->left) + count(ptr->right)+1); } 19

Hloubka stromu (= max hloubka uzlu) rekurzivně Strom nebo podstrom Příklad 3 13 2 2 39 83 1 1 84 58 0 0 0 98 71 5 0 28 m n max(m,n)+1 int depth(node *ptr) { if (ptr == NULL) return (-1); return ( max(depth(ptr->left), depth(ptr->right) )+1 ); } 20

Jednoduchý příklad rekurze Binární pravítko Rysky pravítka Délky rysek Kód vypíše délky rysek pravítka 1 2 1 3 1 2 1 4 1 2 1 3 1 2 1 void ruler(int val) { if (val < 1) return; } ruler(val-1); print(val); ruler(val-1); Call: ruler(4); Domácí úkol: Ternárně!: 21

Binární pravítko vs. průchod inorder Jednoduchý příklad rekurze void ruler(int val) { if (val < 1) return; } Pravítko ruler(val-1); print(val); ruler(val-1); Inorder void listinorder( kód NODE *ptr) { if (ptr == NULL) vypisující return; délky listinorder(ptr->left); rysek printf("%d ", ptr->key); pravítka listinorder(ptr->right); } Strukturní podobnost, shoda! Výstup pravítka 1 2 1 3 1 2 1 4 1 2 1 3 1 2 1 22

Jednoduchý příklad rekurze Činnost binárního pravítka ruler(2); print(3); ruler(2); ruler(3); print(4); ruler(3); 4 if (val < 1) return; ruler(val-1); print(val); ruler(val-1); Start 3 3 2 2 2 2 1 1 1 1 1 1 1 1 ruler(1); print(2); ruler(1); ruler(0); print(1); ruler(0); return; 1 2 1 3 1 2 1 4 1 2 1 3 1 2 1 23

Binární pravítko bez rekurze Zásobník implementuje rekurzi Detail stromu rekurze Uzel A navštíven 1x Uzel A navštíven 0x 1 A 1 2 0 2 0 3 Postup výpočtu Strom rekurze 4 3 3 2 2 2 2 1 1 1 1 1 1 1 1 1 2 1 1 2 2 2 Uzel A navštíven 2x 24

Zásobník implementuje rekurzi Standardní strategie Při používání zásobníku: Je-li to možné, zpracovávej jen data ze zásobníku. Standardní postup Ulož první uzel (první zpracovávaný prvek) do zásobníku. Každý další uzel (zpracovávaný prvek) ulož také na zásobník. Zpracovávej vždy pouze uzel na vrcholu zásobníku. Když jsi s uzlem (prvkem) hotov, ze zásobníku ho odstraň. Skonči, když je zásobník prázdný. 25

Zásobník implementuje rekurzi Každý záběr v následující sekvenci předvádí situaci PŘED zpracováním uzlu. Aktuální pozice Start: Vstup do kořene 4 hodnota Zásobník 4 0 návštěv push(4,0) 3 2 2 1 1 1 1 Výstup 26

Zásobník implementuje rekurzi Průchod stromem rekurze Zásobník Opouštíme 4 a blížíme se k 3 4 hodnota návštěv 4 1 push(3,0) 3 3 0 2 2 1 1 1 1 Výstup 27

Zásobník implementuje rekurzi Průchod stromem rekurze Opouštíme 3 a blížíme se k 2 3 2 2 4 hodnota Zásobník 4 1 3 1 2 0 návštěv push(2,0) 1 1 1 1 Výstup 28

Zásobník implementuje rekurzi Průchod stromem rekurze hodnota Zásobník návštěv 4 4 1 Opouštíme 2 a blížíme 3 se k 1 2 2 1 1 1 1 3 1 2 1 1 0 push(1,0) Výstup 29

Zásobník implementuje rekurzi Průchod stromem rekurze hodnota Zásobník návštěv 4 4 1 Opouštíme 1 a blížíme 3 se k 0 2 2 1 1 1 1 3 1 2 1 1 1 0 0 push(0,0) Výstup 30

Zásobník implementuje rekurzi Průchod stromem rekurze hodnota Zásobník návštěv 4 4 1 Opouštíme 0 a blížíme 3 se k 1 2 2 1 1 1 1 3 1 2 1 1 1 0 0 pop() Výstup 31

Zásobník implementuje rekurzi Průchod stromem rekurze hodnota Zásobník návštěv 4 4 1 Opouštíme 1 a blížíme 3 se k 0 2 2 1 1 1 1 3 1 2 1 1 2 0 0 push(0,0) 1 Výstup 32

Zásobník implementuje rekurzi Průchod stromem rekurze hodnota Zásobník návštěv 4 4 1 Opouštíme 0 a blížíme 3 se k 1 2 2 1 1 1 1 3 1 2 1 1 2 0 0 pop() 1 Výstup 33

Zásobník implementuje rekurzi Průchod stromem rekurze hodnota Zásobník návštěv 4 4 1 Opouštíme 1 a blížíme 3 se k 2 2 2 1 1 1 1 3 1 2 1 1 2 pop() 1 Výstup 34

Zásobník implementuje rekurzi Průchod stromem rekurze hodnota Zásobník návštěv 4 4 1 Opouštíme 2 a blížíme 3 se k 1 2 2 3 2 1 2 push(1,0) 1 1 1 1 1 0 1 2 Výstup atd 35

po chvíli Zásobník implementuje rekurzi Průchod stromem rekurze hodnota Zásobník návštěv Opouštíme 2 a blížíme se k 3 3 4 4 1 3 1 2 2 2 2 pop() 1 1 1 1 1 2 1 Výstup 36

Zásobník implementuje rekurzi Průchod stromem rekurze hodnota Zásobník návštěv Opouštíme 3 a blížíme se k 2 3 2 2 4 4 1 3 2 2 0 push(2,0) 1 1 1 1 1 2 1 3 Výstup atd 37

a je hotovo Zásobník implementuje rekurzi Průchod stromem rekurze 4 Zásobník hodnota návštěv 4 2 (empty == true) pop() 3 2 1 1 1 1 2 1 3 1 2 1 4 1 2 1 3 1 2 1 Výstup 38

Zásobník implementuje rekurzi Rekurzivní pravítko bez rekurzivního volání Pseudokód (skoro kód :-)) pro objektový přístup while (stack.empty() == false) { if (stack.top.hodnota == 0) stack.pop(); if (stack.top.navstev == 0) { stack.top.navstev++; stack.push(stack.top.hodnota-1,0); } if (stack.top.navstev == 1) { print(stack.top.hodnota); stack.top.navstev++; stack.push(stack.top.hodnota-1,0); } if (stack.top.navstev==2) stack.pop(); } 39

int zashodn[10]; int zasnavst[10]; int SP; // SP = Stack Pointer void ruler2() { while (SP >= 0) { if (zashodn[sp] == 0) SP--; // pop if (zasnavst[sp] == 0) { // první návštěva zasnavst[sp]++; SP++; zashodn[sp] = zashodn[sp-1]-1; // jdi doleva zasnavst[sp] = 0; } } } if (zasnavst[sp] == 1) { // druhá návštěva printf("%d%s", zashodn[sp], " ");// zpracuj uzel zasnavst[sp]++; SP++; zashodn[sp] = zashodn[sp-1]-1; // jdi doprava zasnavst[sp] = 0; } if (zasnavst[sp] == 2) SP --; // pop: uzel hotov Zásobník implementuje rekurzi Rekurzivní pravítko bez rekurzivního volání, jednoduchá implementace polem 40

Snadné prohledávání s návratem (Backtrack) Problém osmi dam na šachovnici Některá řešení 0 1 2 3 4 5 6 7 x 0 1 2 3 4 5 6 7 x 0 4 1 6 2 1 3 3 4 7 5 0 6 2 7 5 0 1 2 3 4 5 6 7 0 4 7 5 2 6 1 3 y y Jediná datová struktura xposarray[ ] (viz kód) 41

Snadné prohledávání s návratem (Backtrack) Strom testovaných pozic (kořen a několik potomků) Kam lze položit dámu 42

Snadné prohledávání s návratem (Backtrack) Strom testovaných pozic (výřez) 43

Snadné prohledávání s návratem (Backtrack) Strom testovaných pozic (výřez) Stop! 44

Snadné prohledávání s návratem (Backtrack) N Počet Počet testovaných pozic dámy řešení Hrubá síla (N N ) Backtrack Zrychlení 4 2 256 240 1.07 5 10 3 125 1 100 2.84 6 4 46 656 5 364 8.70 7 40 823 543 25 088 32.83 8 92 16 777 216 125 760 133.41 9 352 387 420 489 651 402 594.75 10 724 10 000 000 000 3 481 500 2 872.33 11 2 680 285 311 670 611 19 873 766 14 356.20 12 14 200 8 916 100 448 256 121 246 416 73 537.00 Tab 3.1 Rychlosti řešení problému osmi dam 45

Snadné prohledávání s návratem (Backtrack) bool posok( int x, int y) { int i; for (i = 0; i < x; i++) if ((xposarr[i] == y) // stejná řada (abs(x-i) == abs(xposarr[i]-y) )) // nebo diagonála return false; return true; } void tryputcolumn(int y) { int x; if (y >= N ) print_xposarr(); // řešení else for (x = 0; x < N; x++) // testuj sloupce if (posok(y, x) == true) { // když je volno, xposarr[y] = x; // dej tam dámu tryputcolumn(y + 1); // a volej rekurzi } } Call: tryputcolumn(0); 46