10.4 Problém třídění

Jak složité je setřídit (uspořádat) zadanou $n$-tici objektů? Abychom na tuto otázku mohli odpovědět, tak si musíme ujasnit co přesně myslíme pod pojmem uspořádat, tj. pod symbolem $\leq$ a jak měřit složitost.

  • Vstup: množina $\{x_1, \ldots, x_n\}$ a úplné uspořádání (viz podkapitolu 11.6) $\leq$ mezi jejími prvky. Velikostí vstupu rozumíme jednoduše počet prvků vstupu.

  • Výstup: uspořádaná $n$-tice $(x_{k_1},\ldots,x_{k_n})$, kde $(k_1,\ldots,k_n)$ je permutace množiny $\{1,\ldots,n\}$ a $x_{k_1} \leq \cdots \leq x_{k_n}$.

  • Elementární operace: porovnání dvou prvků pomocí $\leq$

10.4.1 Bublinkový algoritmus (Bubble sort)

Pro připomenutí uvádíme kompletní algoritmus, zřejmě čtenáři známý z předmětu BI-PA1.

procedure bubbleSort(A : array of length n)
  for k in n-1 to 1 do
    sorted = true
    for i in 1 to k do
      if A[i] > A[i+1] then
        swap( A[i], A[i+1] )
        sorted = false
      end if
    end for
    if sorted then return A
  end for
  return A
end procedure

Celkový počet porovnání může být nejhůře (pokud je na vstupu seznam v přesně opačném pořadí)

\begin{equation*} (n-1) + (n-2) + \cdots + 2 + 1 = \sum_{k=1}^{n-1} k = \frac{n(n-1)}{2}. \end{equation*}

Pokud je na vstupu již setříděný seznam, pak algoritmus provede $(n-1)$ porovnání (nejlepší varianta). Označíme-li počet porovnání při konkrétním vstupu o velikosti $n$ jako $T_n$, můžeme tedy shrnout, že pro složitost Bubble sort platí

\begin{equation*} T_n = \mathcal{O}(n^2). \end{equation*}

10.4.2 Quick sort

Tento algoritmus pochází z roku 1961, viz (Hoare, 1961). Nechť je opět dán vstup $\{x_1,\, x_2,\, \ldots, x_n \}$.

  1. Vyber náhodně prvek ze seznamu (nazývaný pivot).

  2. Prvky ze seznamu menší než pivot, dej do jednoho podseznamu a prvky větší do druhého podseznamu.

  3. Dva kratší seznamy uspořádej podle velikosti.

  4. Spoj uspořádaný první seznam, za něj dej pivota a připoj uspořádaný druhý seznam.

Algoritmus probíhá rekurentně. Uspořádání dvouprvkového seznamu je jednoduché. Označme nyní $T_n$ průměrný počet porovnání pro uspořádání seznamu délky $n$ pomocí algoritmu Quick sort. V příštím semestru ukážeme, že platí

\begin{equation*} \langle T_n \rangle = \mathcal{O}\big( n\, \ln(n) \big). \end{equation*}

Při nešťastné volbě pivotů může být počet porovnání blízko $n^2$.

Vedle zde uvedených dvou algoritmů existuje celá řada dalších třídících algoritmů. Například Merge sort, který i řeší před chvílí zmíněný nedostatek. Tento algoritmus je připisován Johnovi von Neumannovi (1945).