5.3 TopSort

Definice 5.4 (Topologické uspořádání / Topological Sort)

Topologické uspořádání (TU) orientovaného grafu $G = (V, E)$ je takové seřazení vrcholů $V = {v_1, . . . , v_n}$, že pro každou orientovanou hranu $(v_i , v_j ) \in E$ platí $\boldsymbol{i} \boldsymbol{<} \boldsymbol{j}$.

\begin{equation*} (\forall (v_i, v_j) \in E)(i < j) \end{equation*}

  • Jinými slovy, pokud vrcholy zakreslíme horizontálně v pořadí topologického uspořádání, budou všechny orientované hrany směřovat zleva doprava.

  • Topologické uspořádání se používá především pro plánování pořadí provedení navzájem závislých úloh/výpočtů.

Pozorování 5.1

Pokud graf obsahuje cyklus, nelze tuto úlohu zjevně vyřešit

5.3.1 Algoritmus TopSort

Existence zdroje v orientovaném acyklickém grafu vede přímočaře na algoritmus konstrukce topologického uspořádání takového grafu.

Definice 5.5 (TopSort)

Vstup: Orientovaný graf $G$.

Výstup: Nějaké topologické uspořádání $G$, pokud byl acyklický, a detekce cykličnosti v opačném případě.

Poznámka 5.2

Idea:

  • Průběžně počítej vstupní stupně vrcholů (tj. počet hran, ve kterých je vrchol následníkem)

  • Zdroje zařazuj do fronty,

  • Odebírej vrcholy z fronty, zařazuj je do výstupního pořadí a odebírej je z grafu a to znamená, že jejich následníkům snižuj vstupní stupně.

  • Pokud po vyprázdnění fronty zbyly v grafu nějaké vrcholy, byl v něm orientovaný cyklus.

\begin{algorithm}
\begin{algorithmic}
\FUNCTION {TopSort}{orientovaný graf $G$}
    \STATE $Q$ je prázdná fronta
    \STATE $\delta[]$ := pole vstupních stupňů vrcholů $G$,
    na počátku vynulované
    \FOR { každou hranu $(u, v) \in E(G)$ }
        \STATE $\delta[v] + +$
    \ENDFOR
    \STATE Vlož do $Q$ všechny vrcholy z s $\delta[z] = 0$
    \WHILE { $Q$ není prázdná }
        \STATE Odeber prvek $z$ ze začátku fronty $Q$
        \STATE Vypiš $z$
        \FOR { každou hranu $(z, w)$ vedoucí ze $z$ }
            \STATE $\delta[w]−−$
            \IF { Pokud $\delta[w] = 0$ }
                \STATE zařaď $w$ do $Q$ 
            \ENDIF
        \ENDFOR
    \ENDWHILE
    \IF { nebyly zpracovány všechny vrcholy }
        \STATE graf $G$ obsahuje orientovaný cyklus
    \ENDIF
\ENDFUNCTION\end{algorithmic}
\end{algorithm}

Algoritmus 5.3: TopSort

Věta 5.3 (o správnosti algoritmu TopSort)

Algoritmus TopSort ($G$) spuštěný na orientovaný graf $G$ doběhne v konečném čase a buď vygeneruje korektní topologické uspořádání acyklického grafu nebo detekuje existenci orientovaného cyklu.

Zobrazit důkaz

Předpokládejme, že G je orientovaný graf a předpokládejme, že na počátku v kroku (7) existuje aspoň jeden zdroj $z$ a že všechny zdroje zařadíme do fronty $Q$.

\begin{algorithm}
\begin{algorithmic}
\STATE Vlož do $Q$ všechny vrcholy z s $\delta[z] = 0$\end{algorithmic}
\end{algorithm}

Vnitřek cyklu (8)-(17) realizuje odebrání 1 zdroje z fronty Q, jeho vyjmutí z grafu G, jeho vložení do výsledného uspořádání a identifikaci případných nových zdrojů a jejich zařazení do Q.

\begin{algorithm}
\begin{algorithmic}
\WHILE { $Q$ není prázdná }
    \STATE Odeber prvek $z$ ze začátku fronty $Q$
    \STATE Vypiš $z$
    \FOR { každou hranu $(z, w)$ vedoucí ze $z$ }
        \STATE $\delta[w]−−$
        \IF { Pokud $\delta[w] = 0$ }
            \STATE zařaď $w$ do $Q$ 
        \ENDIF
    \ENDFOR
\ENDWHILE\end{algorithmic}
\end{algorithm}

Existence hrany $(v_i , v_j)$ znemožňuje vložit vrchol $v_j$ do fronty $Q$ před vrcholem $v_i$, protože $v_j$ by v takovém okamžiku mělo $\delta[v_j] \gt 1$ a podmínkou vložení do $Q$ je $\delta[v_j] = 0$.

Pokud v okamžiku vyprázdnění fronty jsou zpracovány všechny vrcholy grafu $G$, našli jsme TU orientovaného acyklického grafu.

Pokud je fronta prázdná a přesto zbývají nějaké nezpracované vrcholy ve zbytku $G$, pak ve zbytku $G$ nejsou žádné zdroje, čili každý vrchol má vstupní hranu/-y a musí existovat orientovaný cyklus, plus případně z něj dostupné podgrafy. Vrcholy tohoto zbytkového grafu nelze topologicky uspořádat

Algoritmus tedy správně detekuje existenci cyklu a skončí v konečném čase

V obou případech algoritmus pracuje korektně a zastaví se

$\square$

Věta 5.4 (o složitosti algoritmu TopSort)

Algoritmus TopSort ($G$), kde $G = (V, E)$ je orientovaný graf reprezentovaný pomocí pole následníků, má časovou i paměťovou složitost $O(|V | + |E|)$.

Zobrazit důkaz

Výpočet pole vstupních stupňů na řádcích (4)-(5) trvá $\Theta(|E|)$.

\begin{algorithm}
\begin{algorithmic}
\FOR { každou hranu $(u, v) \in E(G)$ }
    \STATE $\delta[v] + +$
\ENDFOR\end{algorithmic}
\end{algorithm}

Počáteční vložení zdrojů do $Q$ na řádku (7) trvá $O(|V|)$.

\begin{algorithm}
\begin{algorithmic}
\STATE Vlož do $Q$ všechny vrcholy z s $\delta[z] = 0$\end{algorithmic}
\end{algorithm}

Každý vrchol je vložen do $Q$ nejvýše 1x, proto vybírání z $Q$ a výpis na výstup na řádcích (9)–(10) trvá $O(|V|)$.

\begin{algorithm}
\begin{algorithmic}
\STATE Odeber prvek $z$ ze začátku fronty $Q$
\STATE Vypiš $z$\end{algorithmic}
\end{algorithm}

Každá hrana může být odebrána z grafu nejvýše 1x, proto operace na řádcích (11)–(16) trvají $O(|E|)$.

\begin{algorithm}
\begin{algorithmic}
\FOR { každou hranu $(z, w)$ vedoucí ze $z$ }
    \STATE $\delta[w]−−$
    \IF { Pokud $\delta[w] = 0$ }
        \STATE zařaď $w$ do $Q$ 
    \ENDIF
\ENDFOR\end{algorithmic}
\end{algorithm}

Celková časová složitost je tedy $O(|V| + |E|)$.

Graf $G$, pole $\delta[]$, fronta $Q$, to vše zabere $O(|V| + |E|)$ paměti.

$\square$

Otázka 5.1

Jak vypadají orientované grafy s právě dvěma topologickými uspořádáními?

Otázka 5.2

Jak vypadají orientované grafy s právě třemi topologickými uspořádáními?

Otázka 5.3

Fungoval by algoritmus TopSort i s jinou strukturou než frontou? Co třeba se zásobníkem?

Navrhněte, jak modifikovat algoritmus DFS pro orientované grafy, aby vytvořil TU grafu.