Graf a prohledávání do šířky a do hloubky

  • Informatika
  • BFS a DFS rozbor
  • BFS a DFS shrnutí
  • Grafové algoritmy pro…
  • Nejkratší cesta v grafu

Podcast

Reprezentace grafů0:00 / 18:10
0:001:00 zbývá

Vítejte ve světě grafů a prohledávání do šířky a do hloubky! Grafy jsou klíčové struktury v informatice a matematice, které modelují vztahy mezi objekty. Pochopení algoritmů jako je Breadth-First Search (BFS) a Depth-First Search (DFS) je pro studenty naprosto zásadní. Tento článek vám poskytne kompletní rozbor těchto metod prohledávání grafů, jejich principů, využití a pomůže vám vyhnout se běžným chybám. Připravte se na to, že po jeho přečtení budete mít jasno v tom, jak efektivně analyzovat grafové struktury!

Graf a prohledávání do šířky a do hloubky: Základy a metody

Než se pustíme do prohledávání, je důležité si ujasnit, co to vlastně graf je. Graf G je definován jako uspořádaná dvojice (V, E), kde V je množina vrcholů (uzlů) a E je množina hran. Hrany reprezentují spojení mezi vrcholy.

Základní pojmy v grafech

  • Vrchol (uzel): Základní prvek grafu, například město, osoba nebo webová stránka.
  • Hrana: Spojení mezi dvěma vrcholy. Může být orientovaná (s jedním směrem, např. odkaz) nebo neorientovaná (obousměrná, např. přátelství).
  • Vážené hrany: Mají přiřazenou číselnou hodnotu (váhu), například vzdálenost nebo čas.
  • Sousední vrcholy: Dva vrcholy spojené hranou.
  • Stupeň vrcholu: Počet hran incidentních s vrcholem. U orientovaných grafů rozlišujeme vstupní a výstupní stupeň.
  • Cesta: Posloupnost vrcholů spojených hranami.
  • Cyklus: Cesta, která začíná a končí ve stejném vrcholu.
  • Souvislý graf: Graf, ve kterém existuje cesta mezi každými dvěma vrcholy.

Reprezentace grafů v paměti

Pro počítačové zpracování grafů se nejčastěji používají dvě metody:

Matice sousednosti

Je to čtvercová matice V × V. Pokud existuje hrana z i do j, prvek A[i][j] je 1 (nebo váha hrany). Jinak je 0 (nebo nekonečno).

  • Výhody: Rychlé zjištění existence hrany (O(1)). Dobré pro husté grafy.
  • Nevýhody: Paměťová náročnost O(V²), neefektivní pro řídké grafy. Procházení sousedů je O(V).

Seznam sousednosti

Jedná se o pole seznamů, kde pro každý vrchol i existuje seznam jeho sousedů. U vážených grafů se ukládají dvojice (sousední vrchol, váha).

  • Výhody: Paměťová náročnost O(V + E), efektivní pro řídké grafy. Rychlé procházení sousedů (O(stupeň vrcholu)).
  • Nevýhody: Zjištění existence hrany vyžaduje prohledání seznamu (O(stupeň vrcholu)).

Pro většinu algoritmů prohledávání grafů je seznam sousednosti preferovanou reprezentací.

Ověř si, co už víš

Test · 20 otázek · první 3 zdarma

Otázka 1 z 30%

Paměťová náročnost seznamu sousednosti je méně efektivní pro řídké grafy než paměťová náročnost matice sousednosti.

Procvič si to na kartičkách

9 kartiček · první 3 zdarma bez účtu

1 / 9

Jaké dva hlavní způsoby reprezentace grafů existují?

Matice sousednosti a seznam sousednosti.

Klepni pro otočení · Swipni pro navigaci

Prohledávání do šířky (BFS – Breadth-First Search) pro nejkratší cestu

BFS je algoritmus pro procházení grafových struktur, který prozkoumává graf po vrstvách. Začíná se od počátečního vrcholu, navštíví se jeho přímí sousedé, poté sousedé těchto sousedů a tak dále. Je ideální pro nalezení nejkratší cesty v neváženém grafu.

Princip a datová struktura BFS

BFS používá datovou strukturu fronta (Queue), která funguje na principu FIFO (First-In, First-Out – první dovnitř, první ven). Vrcholy jsou zpracovávány v pořadí, v jakém byly objeveny.

Algoritmus BFS krok za krokem

  1. Inicializace: Všechny vrcholy jsou nenavštívené. Vzdálenosti jsou nekonečné, předchůdci null.
  2. Start: Vybereme počáteční vrchol s. Označíme ho jako navštívený, vzdálenost 0, a přidáme do fronty.
  3. Procházení: Dokud fronta není prázdná:
  • Vyjmeme vrchol u z čela fronty.
  • Pro každého souseda v vrcholu u:
  • Pokud v nebyl navštíven:
  • Označíme v jako navštívený.
  • Nastavíme vzdálenost v = vzdálenost u + 1.
  • Nastavíme předchůdce v = u.
  • Přidáme v na konec fronty.

Časová složitost BFS

Každý vrchol je do fronty přidán a z ní vyjmut právě jednou. Každá hrana je prozkoumána nejvýše dvakrát. Časová složitost BFS je proto O(V + E), což je optimální.

Využití BFS

  • Nalezení nejkratší cesty v neváženém grafu: Přirozeně nachází cestu s minimálním počtem hran.
  • Testování souvislosti grafu: Pokud BFS navštíví všechny vrcholy, graf je souvislý.
  • Nalezení komponent souvislosti.
  • Hledání cyklů v neorientovaném grafu.
  • Web crawling: Procházení webových stránek.

Příklad BFS

Mějme graf s vrcholy A-G a hranami (A,B), (A,C), (B,D), (C,E), (D,F), (E,G). Start z A.

  1. Fronta = [A], Navštívené = {A}, Vzdálenost A=0
  2. Vyjmeme A. Sousedé B, C.
  • B nenavštívené: Navštívíme B, Vzdálenost B=1, Předchůdce B=A. Přidáme B. Fronta = [B]
  • C nenavštívené: Navštívíme C, Vzdálenost C=1, Předchůdce C=A. Přidáme C. Fronta = [B, C]
  1. Vyjmeme B. Sousedé A (navštívený), D.
  • D nenavštívené: Navštívíme D, Vzdálenost D=2, Předchůdce D=B. Přidáme D. Fronta = [C, D]
  1. Vyjmeme C. Sousedé A (navštívený), E.
  • E nenavštívené: Navštívíme E, Vzdálenost E=2, Předchůdce E=C. Přidáme E. Fronta = [D, E]
  1. Vyjmeme D. Sousedé B (navštívený), F.
  • F nenavštívené: Navštívíme F, Vzdálenost F=3, Předchůdce F=D. Přidáme F. Fronta = [E, F]
  1. Vyjmeme E. Sousedé C (navštívený), G.
  • G nenavštívené: Navštívíme G, Vzdálenost G=3, Předchůdce G=E. Přidáme G. Fronta = [F, G]
  1. Vyjmeme F. Sousedé D (navštívený).
  2. Vyjmeme G. Sousedé E (navštívený).
  3. Fronta prázdná. Konec.

Výsledné vzdálenosti: A=0, B=1, C=1, D=2, E=2, F=3, G=3. Nejkratší cesta k F je F ← D ← B ← A.

Prohledávání do hloubky (DFS – Depth-First Search) a jeho principy

DFS prozkoumává graf tak hluboko, jak je to jen možné podél jedné cesty, než se vrátí zpět a prozkoumá další větve. Je to jako procházet bludištěm – jdete jednou cestou, dokud nenarazíte na slepou uličku, a pak se vrátíte k poslední křižovatce a zkusíte jinou cestu.

Princip a datová struktura DFS

DFS používá datovou strukturu zásobník (Stack), která funguje na principu LIFO (Last-In, First-Out – poslední dovnitř, první ven). Lze ji implementovat i rekurzivně, přičemž rekurzivní volání využívají implicitní zásobník operačního systému.

Algoritmus DFS krok za krokem

  1. Inicializace: Všechny vrcholy v grafu jsou nenavštívené.
  2. Start: Vybereme počáteční vrchol s. Přidáme ho do zásobníku a označíme ho jako navštívený.
  3. Procházení (iterativní): Dokud zásobník není prázdný:
  • Vyjmeme vrchol u z vrcholu zásobníku.
  • Pro každého souseda v vrcholu u:
  • Pokud v nebyl dosud navštíven:
  • Označíme v jako navštívený.
  • Přidáme v do zásobníku.

Rekurzivní implementace DFS je často elegantnější:

DFS(vrchol u):
 Označ u jako navštívený
 Pro každého souseda v vrcholu u:
 Pokud v není navštívený:
 DFS(v)

Časová složitost DFS

Stejně jako BFS je i DFS časová složitost O(V + E), protože každý vrchol a hrana jsou zpracovány konstantní počet krát.

Využití DFS

  • Hledání cyklů: Efektivní pro detekci cyklů v grafech.
  • Topologické řazení: Pro orientované acyklické grafy (DAG).
  • Nalezení komponent souvislosti (neorientovaný graf) nebo silně souvislých komponent (orientovaný graf).
  • Řešení bludišť: DFS přirozeně prozkoumává jednu cestu až do konce.
  • Prohledávání stavového prostoru: V umělé inteligenci.

Příklad DFS

Stejný graf jako u BFS, start z A. Rekurzivní DFS (abecední pořadí sousedů):

DFS(A):
 Navštívené = {A}
 Sousedé A: B, C
 DFS(B):
 Navštívené = {A, B}
 Sousedé B: A, D
 A je navštívené
 DFS(D):
 Navštívené = {A, B, D}
 Sousedé D: B, F
 B je navštívené
 DFS(F):
 Navštívené = {A, B, D, F}
 Sousedé F: D
 D je navštívené
 (návrat z DFS(F))
 (návrat z DFS(D))
 (návrat z DFS(B))
 DFS(C):
 Navštívené = {A, B, D, F, C}
 Sousedé C: A, E
 A je navštívené
 DFS(E):
 Navštívené = {A, B, D, F, C, E}
 Sousedé E: C, G
 C je navštívené
 DFS(G):
 Navštívené = {A, B, D, F, C, E, G}
 Sousedé G: E
 E je navštívené

 (návrat z DFS(G))
 (návrat z DFS(E))
 (návrat z DFS(C))
(návrat z DFS(A))

Pořadí navštívených vrcholů: A, B, D, F, C, E, G.

Porovnání BFS a DFS: Klíčové rozdíly a využití

Oba algoritmy mají stejnou asymptotickou časovou složitost O(V + E), ale liší se v chování a vhodnosti pro různé úlohy. Pochopení těchto rozdílů je pro studenty velmi důležité.

VlastnostProhledávání do šířky (BFS)Prohledávání do hloubky (DFS)
PrincipProchází graf po vrstvách, od nejbližších k nejvzdálenějšímProchází graf co nejhlouběji podél jedné cesty, pak se vrací
Datová strukturaFronta (Queue)Zásobník (Stack) nebo rekurze
Nalezení nejkratší cestyAno, v neváženém grafu (v počtu hran)Ne, nenachází nejkratší cestu
Paměťová náročnostO(V) v nejhorším případě (pro široké grafy)O(V) v nejhorším případě (pro hluboké grafy)
VyužitíNejkratší cesta, komponenty souvislosti, web crawlingDetekce cyklů, topologické řazení, silně souvislé komponenty

Běžné chyby a nedorozumění u BFS a DFS

Studenti se často setkávají s několika typickými chybami. Zde je jejich shrnutí, které vám pomůže se jim vyhnout:

  1. Záměna fronty a zásobníku: Toto je nejčastější chyba. BFS používá frontu (FIFO), DFS zásobník (LIFO) nebo rekurzi. Záměna vede k odlišnému chování a výsledkům.
  2. Zapomenutí na značení navštívených vrcholů: Pokud se vrcholy neoznačí jako navštívené, algoritmus může vstoupit do nekonečné smyčky v grafech s cykly, nebo opakovaně zpracovávat stejné vrcholy, což snižuje efektivitu.
  3. Předpoklad nejkratší cesty u DFS: DFS nenajde nejkratší cestu v neváženém grafu. Jeho hloubkové prohledávání může vést k dlouhým cestám, i když existují kratší alternativy. Pro nejkratší cestu použijte vždy BFS.
  4. Nesprávné použití pro vážené grafy: Ani BFS, ani DFS nejsou určeny k nalezení nejkratší cesty ve vážených grafech. Pro tyto účely se používají jiné algoritmy, například Dijkstraův algoritmus nebo Bellman-Fordův algoritmus.
  5. Chybné zpracování odpojených komponent: Pokud graf není souvislý, BFS/DFS navštíví pouze vrcholy v komponentě startovního vrcholu. Pro prohledání celého grafu je nutné algoritmy spouštět opakovaně z dosud nenavštívených vrcholů.

Simulace prohledávání grafů pro lepší pochopení

Interaktivní simulace prohledávání grafů je vynikající nástroj pro hlubší pochopení BFS a DFS. Můžete na nich pozorovat a zkoušet následující:

  • Krokování algoritmu: Procházejte algoritmus krok za krokem a vizualizujte, jak se vrcholy přidávají a odebírají z fronty/zásobníku a jak se mění stavy vrcholů.
  • Vizualizace fronty/zásobníku: Sledujte aktuální obsah fronty nebo zásobníku. To jasně demonstruje vrstvové prohledávání BFS a hloubkové prohledávání DFS.
  • Změna počátečního vrcholu: Vyzkoušejte spustit BFS/DFS z různých počátečních vrcholů a pozorujte změny v pořadí navštívených vrcholů.
  • Porovnání cest: U BFS si všimněte, jak se postupně objevují nejkratší cesty. U DFS uvidíte, že nalezené cesty mohou být delší a klikatější.
  • Vliv struktury grafu: Experimentujte s různými typy grafů (řídké, husté, s cykly, bez cyklů, orientované, neorientované) a pozorujte, jak se mění chování algoritmů.
  • Detekce cyklů (DFS): V simulaci DFS si můžete všimnout, jak algoritmus detekuje cykly, když narazí na navštíveného souseda, který není přímým předchůdcem.

Simulace poskytuje názorný způsob, jak upevnit teoretické znalosti a porozumět praktickým důsledkům volby mezi BFS a DFS pro konkrétní úlohy.

FAQ: Nejčastější otázky k BFS a DFS

Kdy použít BFS a kdy DFS?

BFS je ideální pro nalezení nejkratší cesty v neváženém grafu, testování souvislosti nebo procházení po vrstvách (např. web crawling). DFS se lépe hodí pro detekci cyklů, topologické řazení, hledání komponent souvislosti nebo řešení bludišť, kde potřebujete prozkoumat cestu do hloubky.

Jaká je paměťová složitost BFS a DFS?

Oba algoritmy mají v nejhorším případě paměťovou složitost O(V). U BFS to nastává u širokých grafů, kde je mnoho vrcholů v jedné vrstvě ve frontě. U DFS se O(V) projevuje u hlubokých grafů, kdy zásobník (nebo rekurzní volání) může obsahovat mnoho vrcholů na jedné dlouhé cestě.

Je možné najít nejkratší cestu pomocí DFS?

Ne, DFS nenajde nejkratší cestu v neváženém grafu. DFS prozkoumává graf do hloubky a může tak objevit velmi dlouhou cestu k cílovému vrcholu, i když existuje mnohem kratší. Pro nejkratší cestu v neváženém grafu je vždy nutné použít BFS.

Jaké jsou hlavní datové struktury pro BFS a DFS?

BFS primárně používá frontu (Queue), která dodržuje princip FIFO (First-In, First-Out). DFS používá zásobník (Stack), který dodržuje princip LIFO (Last-In, First-Out), nebo je implementováno rekurzivně, přičemž rekurze využívá implicitní zásobník operačního systému.

Procvič si to, ne jen přečti

9 kartiček, test s vysvětlením a podcast k tomuto tématu. Účet je zdarma a pokračuješ tam, kde jsi skončil.

  • Bez platební karty
  • Web i mobilní aplikace
  • 330 000+ studentů
Začni zdarma

Související témata