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

Podobné dokumenty
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.

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

Úvod do teorie grafů

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.

ORIENTOVANÉ GRAFY, REPREZENTACE GRAFŮ

Vzdálenost uzlů v neorientovaném grafu

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

Jan Březina. 7. března 2017

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

Konstruktory a destruktory

TGH05 - aplikace DFS, průchod do šířky

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

PROHLEDÁVÁNÍ GRAFŮ. Doc. RNDr. Josef Kolář, CSc. Katedra teoretické informatiky, FIT České vysoké učení technické v Praze

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

Grafové algoritmy. Programovací techniky

Grafové algoritmy. Programovací techniky

Prohledávání do šířky = algoritmus vlny

Dynamické programování

NEJKRATŠÍ CESTY I. Doc. RNDr. Josef Kolář, CSc. Katedra teoretické informatiky, FIT České vysoké učení technické v Praze

Dynamické datové struktury I.

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

Hledáme efektivní řešení úloh na grafu

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

TGH05 - aplikace DFS, průchod do šířky

Datové struktury. alg12 1

Algoritmy na ohodnoceném grafu

07 Základní pojmy teorie grafů

Matice sousednosti NG

Algoritmy a datové struktury

Stromy, haldy, prioritní fronty

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

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

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

Šablony, kontejnery a iterátory

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

Dynamické datové struktury IV.

Abstraktní datové typy

Algoritmizace prostorových úloh

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

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

Obsah prezentace. Základní pojmy v teorii o grafech Úlohy a prohledávání grafů Hledání nejkratších cest

Úloha ve stavovém prostoru SP je <s 0, C>, kde s 0 je počáteční stav C je množina požadovaných cílových stavů

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

Použití dalších heuristik

Prioritní fronta, halda

Šablony, kontejnery a iterátory

Základní datové struktury

6. Tahy / Kostry / Nejkratší cesty

bfs, dfs, fronta, zásobník

ALGORITMY A DATOVÉ STRUKTURY

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

Dynamické datové struktury III.

Algoritmizace prostorových úloh

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

Základy informatiky. Teorie grafů. Zpracoval: Pavel Děrgel Úprava: Daniela Szturcová

Datové typy a struktury

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.

Algoritmizace prostorových úloh

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

Rekurzivní algoritmy

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

TGH07 - Chytré stromové datové struktury

Grafy. RNDr. Petra Surynková, Ph.D. Univerzita Karlova v Praze Matematicko-fyzikální fakulta.

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

Abstraktní datové typy: zásobník

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

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

Základy informatiky. 07 Teorie grafů. Kačmařík/Szturcová/Děrgel/Rapant

ADT prioritní fronta. Haldy. Další operace nad haldou. Binární halda. Binomické stromy. Časová složitost jednotlivých operací.

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

Grafy. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 13.

Prohledávání do šířky a do hloubky. Jan Hnilica Počítačové modelování 15

Dijkstrův algoritmus

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

Lineární datové struktury

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

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

Kapitola 11. Vzdálenost v grafech Matice sousednosti a počty sledů

Výhody a nevýhody jednotlivých reprezentací jsou shrnuty na konci kapitoly.

ABSTRAKTNÍ DATOVÉ TYPY (ADT)

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

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

Časová a prostorová složitost algoritmů

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

STACK

TGH07 - Chytré stromové datové struktury

4 Stromy a les. Definice a základní vlastnosti stromů. Kostry grafů a jejich počet.

Kolekce, cyklus foreach

Implementace LL(1) překladů

Datové struktury 1: Základní datové struktury

Algoritmy výpočetní geometrie

Přijímací zkouška - matematika

PQ-stromy a rozpoznávání intervalových grafů v lineárním čase

1 Nejkratší cesta grafem

Martin Flusser. December 15, 2016

Spojový seznam. Jan Kybic.

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

Hanojská věž. T2: prohledávání stavového prostoru. zadání [1 1 1] řešení [3 3 3] dva možné první tahy: [1 1 2] [1 1 3]

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

Transkript:

LG 04 Zásobník Fronta Operace nqueue, equeue, Front, mpty... yklická implementace fronty Průchod stromem do šířky Grafy průchod grafem do šířky průchod grafem do hloubky Ořezávání a heuristiky 1

Zásobník / stack Prvky se před zpracováním vkládají na vrchol zásobníku. 84 75 Vrchol / top 60 1373 84 14 55 11 71 08 44 3 74 Prvky se odebírají z vrcholu zásobníku a pak se zpracovávají. Operace Vlož na vrchol Push Odeber z vrcholu Pop Čti začátek Top Je prázdný? mpty

Fronta / queue 75 84 Čelo / front Konec / tail 1373 60 14 55 11 71 08 44 3 84 74 Prvky se před zpracováním vkládají na konec fronty. Prvky se odebírají z čela fronty a pak se zpracovávají. Operace Vlož na konec nqueue / InsertLast / Push... Odeber ze začátku equeue / delfront / Pop... Čti začátek Front / Peek... Je prázdná? mpty 3

Fronta Čelo Konec Jednoduchý příklad života fronty Prázdná Vlož(4) Vlož(11) Vlož(90) Odeber() 4 4 11 4 11 90 11 90 Vlož(43) 11 90 43 Odeber() Odeber() 90 43 43 Vlož(79) 43 79 4

yklická implementace fronty polem Čelo Konec Prázdná fronta v poli pevné délky Vlož 4, 11, 90, 43, 70. 4 11 90 43 70 Odeber, odeber, odeber. 43 70 Vlož 10, 0. 0 43 70 10 Odeber, odeber. 0 10 Vlož 55,, 33. 0 55 33 10 Odeber, odeber. 55 33 5

yklická implementace fronty polem Index/ukazatel konce fronty ukazuje na první volnou pozici za posledním prvkem fronty. Index/ukazatel čela fronty ukazuje na první obsazenou pozici. Pokud oba ukazují tamtéž, fronta je prázdná. class Queue { Node q []; int size; int front; int tail; Queue( int qsize ){ size = qsize; q = new Node[size]; front = 0; tail = 0; } boolean mpty() { return ( tail==front ); } void nqueue( Node node ){ if( (tail+1 == front) (tail-front == size-1) )... // queue full, fix it } q[t++] = node; if( tail==size ) tail = 0; Node equeue() { Node n = q[front++]; if( front == size ) front = 0; return n; } } // end of Queue 6

Průchod stromem do šířky Strom s naznačeným směrem průchodu 30 1 71 1 5 8 03 13 63 73 93 Pořadí uzlů 54 64 30 1 71 1 5 8 03 13 63 73 93 54 64 Struktura stromu ani rekurzivní přístup tento průchod nepodporují. 7

Průchod stromem do šířky Inicializace 30 Vytvoř prázdnou frontu 1 71 1 03 13 5 63 8 73 93 o fronty vlož kořen stromu 54 64 30. Čelo Konec Hlavní cyklus okud není fronta prázdná, opakuj: 1. Odeber první uzel z fronty a zpracuj ho.. o fronty vlož jeho potomky, pokud existují. 8

Průchod stromem do šířky x 30 1. x = Odeber(), tisk (x.key). 1 71 1 5 8 03 13 63 73 93 30. Vlož(x.left), vlož(x.right). *) 30 1 1 03 13 54 64 x 30 71 5 8 63 73 93 1 1.. 1 71 x = Odeber(), tisk(x.key). 71 Vlož(x.left), vlož(x.right). *) *) pokud existuje 30 1 54 64 71 1 9

Průchod stromem do šířky 30 x 1. x = Odeber(), tisk (x.key). 1 71 1 1 5 8 71 03 13 63 73 93. Vlož(x.left), vlož(x.right). *) 54 64 30 1 71 30 1 71 x 1. 1 5 8 x = Odeber(), tisk(x.key). 5 8 *) pokud existuje 1 5 8 1 03 13 63 73 93. Vlož(x.left), vlož(x.right). *) 54 64 5 8 03 13 30 1 71 1 10

Průchod stromem do šířky 1 30 71 x 1. x = Odeber(), tisk (x.key). 8 03 13 1 5 8 5 03 13 63 73 93. Vlož(x.left), vlož(x.right). *) 54 64 30 1 71 1 5 30 1 71 x 1. 8 03 13 63 x = Odeber(), tisk(x.key). 03 13 63 *) pokud existuje 1 5 8 8 03 13 63 73 93. Vlož(x.left), vlož(x.right). *) 54 64 03 13 63 73 93 30 1 71 1 5 8 11

Průchod stromem do šířky 1 30 71 x 1. x = Odeber(), tisk (x.key). 13 63 73 93 1 5 8 03 03 13 63 73 93. Vlož(x.left), vlož(x.right). *) 54 64 30 1 71 1 5 8 03 30 x 1 71 1. 13 63 73 93 x = Odeber(), tisk(x.key). 63 73 93 *) pokud existuje 1 5 8 13 03 13 63 73 93. Vlož(x.left), vlož(x.right). *) 54 64 63 73 93 30 1 71 1 5 8 03 13 1

Průchod stromem do šířky 1 30 71 x 1. x = Odeber(), tisk (x.key). 73 93 1 5 8 63 03 13 63 73 93. Vlož(x.left), vlož(x.right). *) 54 64 30 1 71 1 5 8 03 13 63 30 x 1 71 1. 73 93 54 64 x = Odeber(), tisk(x.key). 93 54 64 *) pokud existuje 1 5 8 73 03 13 63 73 93. Vlož(x.left), vlož(x.right). *) 54 64 30 1 71 1 5 8 03 13 63 73 93 54 64 13

Průchod stromem do šířky 1 30 71 x 1. x = Odeber(), tisk (x.key). 54 64 1 5 8 93 03 13 63 73 93. Vlož(x.left), vlož(x.right). *) 54 64 54 64 30 1 71 1 5 8 03 13 63 73 93 1. x = Odeber(), tisk(x.key). 30 x 1 71 64 54 1 5 8 Vlož(x.left), vlož(x.right). *) 03 13 63 73 93. *) pokud existuje 54 64 30 1 71 1 5 8 03 13 63 73 93 54 64 14

Průchod stromem do šířky 1. x = Odeber(), tisk (x.key). 30 x 1 71 64 1 5 8 Vlož(x.left), vlož(x.right). *) 03 13 63 73 93. 54 64 30 1 71 1 5 8 03 13 63 73 93 54 64 *) pokud existuje Fronta je prázdná, průchod stromem končí. V neprázdné frontě jsou vždy právě -- některé (třeba všechny) uzly jednoho patra -- a všichni potomci těch uzlů tohoto patra, které už nejsou ve frontě. Někdy jsou ve frontě přesně všechny uzly jednoho patra. Viz výše. 15

Průchod stromem do šířky void traversetreereadthfirst( Node node ) { if( node == null ) return; Queue q = new Queue(); // init q.nqueue( node ); // root into queue while(!q.mpty() ) { node = q.equeue(); print( node.key ); // process node if( node.left!= null ) q.nqueue( node.left ); if( node.right!= null ) q.nqueue( node.right ); } } 16

Grafy graf je uspořádaná dvojice a b o množiny vrcholů V a o množiny hran G = (V, ) příklad: V = {a, b, c, d, e} = {{a,b},{b,e},{b,c}, {c,e},{e,d}} d c e 17

Grafy - orientovanost neorientovaný graf o hrana je neuspořádaná dvojice vrcholů = {{a,b},{b,e},{b,c}, {c,e},{e,d}} orientovaný graf o hrana je uspořádaná dvojice vrcholů = {{a,b},{b,e},{b,c}, {c,e},{e,d}} a b a b c c d e d e 18

Grafy matice sousednosti Nechť G = (V, ) je graf s n vrcholy Označme vrcholy v 1,, v n (v nějakém libovolném pořadí) Matice sousednosti grafu G je čtvercová matice ( a ) n G i, j i, j 1 definovaná předpisem a i, j 1 pro{ v, v 0 jinak i j } 19

Grafy matice sousednosti pro orientovany graf a b c d e a 0 1 0 0 0 b 0 0 1 0 1 a b c 0 0 0 0 1 d 0 0 0 0 0 e 0 0 0 1 0 d c e 0

Grafy seznam sousedů Nechť G = (V, ) je (ne)orientovaný graf s n vrcholy Označme vrcholy v 1,, v n (v nějakém libovolném pořadí) Seznam sousedů grafu G je pole P ukazatelů velikosti n kde P[i] ukazuje na spojový seznam vrcholů, se kterými je vrchol v i spojen hranou a b b a c e a b c d e b e c e b d d c e 1

Průchod grafem do hloubky Matice sousednosti Spojová reprezentace F G H H G F G G H G F F G H 0 1 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 1 1 0 1 1 1 0 1 0 1 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 1 0 0 0 1 1 0 1 0 1 0 0 0 0 1 0 1 0

Průchod grafem do hloubky 1/- F /- 3/- G 4/- H 1/- Zásobník Zásobník 1/- /- 1/- F /- 3/- G H Zásobník G Zásobník G H G G H 3

Průchod grafem do hloubky 1/- /- 5/- 1/- /- 5/6 3/- 4/- 3/- 4/- Zásobník G H Zásobník G H G H G H 5/6 1/- /- 1/- /- 5/6 3/- 4/7 8/- 3/- 4/7 Zásobník G Zásobník G F G H G H F 4

Průchod grafem do hloubky 5/6 1/- /- 1/- /- 5/6 8/9 3/- 4/7 8/9 3/10 4/7 Zásobník G Zásobník G H F G H F 11/- 11/- 1/- 1/- /- 5/6 1/- /- 5/6 8/9 3/10 4/7 8/9 3/10 4/7 Zásobník Zásobník G H F G H F 5

Průchod grafem do hloubky 1/13 11/- 1/- /- 5/6 8/9 3/10 4/7 8/9 3/10 4/7 Zásobník Zásobník G H F G H F 1/13 11/14 1/- 5/6 /- 1/13 11/14 1/- 5/6 /15 8/9 3/10 4/7 1/13 11/14 1/16 5/6 /15 8/9 3/10 4/7 Zásobník Zásobník G H F G H F 6

Průchod grafem do hloubky Životní cyklus uzlu při prohledávání grafu Fresh - open - closed ( čerstvý - otevřený - uzavřený ) Fresh Open losed Čerstvé uzly jsou všechny dosud ani jednou nenavštívené uzly. Před začátkem prohledávání jsou všechny uzly čerstvé. Při první návštěvě uzlu se uzel stává otevřeným. Množina čerstvých uzlů se během prohledávání nikdy nezvětšuje vzhledem k inkluzi. Otevřené uzly jsou alespoň jednou navštívené uzly, které dosud nebyly uzavřeny. Množina otevřených uzlů se může během prohledávání zvětšovat i zmenšovat. Uzavřené uzly jsou uzly, které už během prohledávání nebudou navštíveny. Pokud jsou všechny sousedy aktuálního uzlu otevřené nebo uzavřené, aktuální uzel se stává uzavřeným. Množina uzavřených uzlů se během prohledávání nikdy nezmenšuje vzhledem k inkluzi. Na konci prohledávání jsou všechny uzly uzavřené. 7

Průchod grafem do hloubky Implementační poznámka Fresh: Čerstvý uzel nemá přiřazen otevírací (ani zavírací) čas. Open: Otevřený uzel nemá přiřazen zavírací čas. losed: Uzavřený uzel má přiřazen zavírací čas. Otevírací a zavírací časy uzlů v některých případech prohledávání není nutno udržovat. Při iterativním prohledávání s vlastním zásobníkem je ale nutno průběžně udržovat informaci u každého uzlu, zda je čerstvý, otevřený nebo zavřený. V rekurzivním zpracování není nutno dělat explicitně ani to. Každé volání rekurzivní funkce odpovídá zpracování jednoho uzlu a všem jeho návštěvám. Při zavolání funkce se otevírá uzel, který je aktuálním parametrem volání, a na konci volání se tento uzel uzavírá. V těle funkce probíráme postupně sousedy aktuálního uzlu a voláme rekurzivně prohledávání pouze na ty z nich, které jsou ještě čerstvé (fresh). Stačí pak v každém uzlu udržovat jen informaci jednobitovou -- fresh nebo not fresh. 8

Průchod grafem do hloubky Postupný obsah zásobníku G G H G H G H G G F G -- Výpis (zpracování) uzlu při otevírání uzlu vede na posloupnost G H F Výpis (zpracování) uzlu při zavírání uzlu vede na posloupnost H F G Zpracování uzlu při jeho závírání se uplatní např. při hledání mostů nebo artikulací v neorientovaném grafu a při detekci silně souvislých komponent v orientovaném grafu. 9

Průchod grafem do hloubky Strom průchodu do hloubky s otevíracími a zavíracími časy jednotlivých uzlů 1/13 11/14 1/16 5/6 /15 3/10 G /15 1/16 11/14 8/9 3/10 4/7 4/7 H 8/9 F 1/13 5/6 Všimněme si, že v podstromu s kořenem X pro každý uzel Y různý od X platí Open_time(X) Open_time(Y) lose_time(y) lose_time(x). Naopak, pokud Y neleží v podstromu s kořenem X, pak platí lose_time(x) Open_time(Y) nebo lose_time(y) Open_time(X) Počet uzlů v podstromu s kořenem X je pak ( lose_time(y) + 1 Open_time(X) ) /. 30

Průchod grafem do hloubky void FS_rec_full( int start ) { vector<int> opent( N, 0 ); vector<int> closet( N, 0 ); vector<int> pred( N, -1 ); // -1 == no predecessor int time = 0; FS_rec_full( start, time, opent, closet, pred ); } for( int n = 0; n < N; n++ ) cout << "node " << n << " open/close " << opent[n] << "/"<< closet[n] << " pred " << pred[n] << endl; 31

Průchod grafem do hloubky rekurzivně void FS_rec_full( int currnode, int & time, vector<int> & opent, vector<int> & closet, vector<int> & pred ){ } int neigh; opent[currnode] = ++time; for( int j = 0; j < edge[currnode].size(); j++ ){ neigh = edge[currnode][j]; if( opent[neigh] == 0 ) { pred[neigh] = currnode; FS_rec_full( neigh, time, opent, closet, pred ); cout << currnode << " --> " << neigh << endl; } } closet[currnode] = ++time; 3

Průchod grafem do hloubky rekurzivně, základní varianta void FS_rec_plain( int currnode, vector<bool> & fresh ){ int neigh; fresh[currnode] = false; for( int j = 0; j < edge[currnode].size(); j++ ){ neigh = edge[currnode][j]; if( fresh[neigh] ) { FS_rec_plain( neigh, fresh ); cout << currnode << " --> " << neigh << endl; } } } void FS_rec_plain( int start) { vector<bool> fresh( N, true ); FS_rec_plain(start, fresh); } 33

Průchod grafem do šířky Životní cyklus uzlu při prohledávání grafu je koncepčně identický jako při prohledávání do hloubky Fresh Open losed Čerstvé uzly jsou všechny dosud ani jednou nenavštívené uzly. Před začátkem prohledávání jsou všechny uzly čerstvé. Při první návštěvě uzlu se uzel stává otevřeným. Množina čerstvých uzlů se během prohledávání nikdy nezvětšuje vzhledem k inkluzi. Otevřené uzly jsou alespoň jednou navštívené uzly, které dosud nebyly uzavřeny. Množina otevřených uzlů se může během prohledávání zvětšovat i zmenšovat. Uzavřené uzly jsou uzly, které už během prohledávání nebudou navštíveny. Pokud jsou všechny sousedy aktuálního uzlu otevřené nebo uzavřené, aktuální uzel se stává uzavřeným. Množina uzavřených uzlů se během prohledávání nikdy nezmenšuje vzhledem k inkluzi. Na konci prohledávání jsou všechny uzly uzavřené. 34

Průchod grafem do šířky 0 0 1 Fronta Fronta 0 1 0 1 1 1 1 Fronta F Fronta F G 35

Průchod grafem do šířky 0 1 0 1 1 1 1 1 Fronta F G Fronta F G 0 1 0 1 1 1 1 1 Fronta F G Fronta F G 36

Průchod grafem do šířky 0 1 0 1 1 1 1 1 Fronta F G Fronta G F F G 0 1 0 1 1 1 1 1 Fronta H Fronta H F G F G 37

Průchod grafem do šířky 0 1 0 1 1 1 1 1 Fronta H Fronta H F G F G 0 1 0 1 1 1 1 1 Fronta H Fronta F G H F G H 38

Průchod grafem do šířky Strom průchodu do šířky s vzdálenostmi od kořene jednotlivých uzlů 0 0 1 1 1 1 F G 1 1 H Hloubka uzlu ve stromu průchodu do šířky je rovna jeho vzdálenosti od startovního uzlu. Na rozdíl od průchodu do hloubky nejsou otevírací a zavírací časy důležité. Průchod do šířky se uplatní např. při testování souvislosti grafu, testování existence cyklů ve grafu, testování bipartitnosti a zejména při výpočtu vzdálenosti mezi startovním a cílovým uzlem. 39

Průchod grafem do šířky Implementační poznámka Fresh: Čerstvý uzel nemá přiřazenu vzdálenost od startovního uzlu. Open: Otevřený uzel má přiřazen zavírací čas a je ve frontě. losed: Uzavřený uzel má přiřazen zavírací čas a není ve frontě. Stavy fresh/open/closed není nutno explicitně udržovat, obsah fronty společně s vzdáleností jednoznačně tyto stavy určují každému uzlu. Průchod do šířky je iterativní postup, rekurzivní varianta se nepoužívá (byla pouze nepřehlednější ). 40

Průchod grafem do šířky Pseudokód void graphreadthfirstsearch( Node startnode ) { Set visited = new Set(); // visited == not fresh Queue q = new Queue(); q.nqueue( startnode ); visited.add( startnode ); while(!q.mpty() ) { node = q.equeue(); print( node.key ); // process node forall x in node.neighbors() if( x not in visited ){ visited.add( x ); q.nqueue( x ); } } } 41

Průchod grafem do šířky v ++ void FS( int start ){ queue<int> q; vector<int> dist( N, -1 ); // -1... fresh node vector<int> pred( N, -1 ); // -1... no predecessor (yet) q.push( start ); dist[start] = 0; int currn, neigh; while(!q.empty() ){ currn = q.front(); q.pop(); cout << "node " << currn << endl; // process the node for( int j = 0; j < edge[currn].size(); j++ ){ neigh = edge[currn][j]; if( dist[neigh] == -1 ){ // neigh is fresh q.push( neigh ); dist[neigh] = dist[currn] + 1; pred[neigh] = currn; cout << "FS edge: " << currn << "->" << neigh << endl; } } } } 4

Průchod grafem do hloubky i do šířky symptotická složitost Každá jednotlivá operace se zásobníkem/frontou a s použitými datovými strukturami má konstantní složitost pro jeden uzel (včetně inicializace). Každý uzel jen jednou vstoupí do zásobníku/fronty a jednou z ní vystoupí. Stav uzlu (fresh/open/closed) se testuje tolikrát, kolik je stupeň tohoto uzlu. Součet stupnů všech uzlů je roven dvojnásobku počtu hran. elkem ( V + ). 43

Ořezávání Urychlení prohledávání Ořezávání neperspektivních větví Pokud jsme schopni na základě vyhodnocení momentálního stavu zjistit, že je to stav neperspektivní a že rozhodně nepovede k řešení úlohy odřízneme ze stromu celý podstrom momentálního stavu Strom prohledávání Momentální stav 44

Příklad ořezávání magický čtverec Magický čtverec řádu N o čtvercové schéma čísel velikost N x N o obsahuje právě jednou každé celé číslo od 1 do N o součet čísel ve všech řádcích a ve všech sloupcích stejný Příklad 9 4 7 5 3 6 1 8 Triviální řešení: generování všech možných rozmístění čísel od 1 do N Ořezávání: kdykoliv je součet na řádku neperspektivní o součet všech čísel čtverce je ½ N (N +1) o součet čísel na řádku je ½ N (N +1) 45

Heuristiky Heuristika je návod, který nám říká, jaký postup řešení úlohy vede obvykle k rychlému dosažení výsledku. Nezaručuje vždy zrychlení výpočtu. Heuristika se používá pro stanovení pořadí, v jakém se zkoumají možné průchody stromem/grafem Příklad: úloha projít šachovým koněm celou šachovnici N x N účinná heuristika: nejprve se navštíví ta dosud nenavštívená pole, z nichž bude nejméně možností dalšího bezprostředního pokračování cesty koně. urychlení na šachovnici 8 x 8 až stotisíckrát. 46