Výběr pivota

Víme jak funguje quicksort a taky si můžeme snadno ověřit, že by bylo ideální jako pivota vybírat medián. Každé rekurzivní volání quicksortu by potom dostalo ke zpracování přibližně poloviční díl.

Výpočet mediánu

Jak ale nalézt medián abychom se moc "nenadřeli"?

Rekurzivní algoritmus, který byl představen na cvičení je znám už dlouho. Na cvičení jsme programovali funkci, která nalezne medián v posloupnosti 5 prvků.

Mergesort

Další z řady třídících algoritmů. Tento rekurzivní algoritmus jsme si vyzkoušeli na vlastní kůži. Pseudokód:

mergesort(L,R,A)
A - vstupni posloupnost
L - levy index trideneho useku
R - pravy index trideneho useku
if L+1 = R then // trivialni pripad dvouprvkove posloupnosti
  if A[L] >= A[R] then
    prohod(A[L],A[R])
  exit

if L < R then
  M:= (R + L) div 2 // index poloviny puvodniho useku
  mergesort(L,M,A)
  mergesort(M+1,R,A)
  merge(L,M,R,A) // slej oba useky a vysledek zapis zpet do A  

Procedura merge přitom vypadá takto:


merge(L,M,R,A)
B - pomocne pole delky (R-L)
[L,M] - prvni usek
[M+1,R] - druhy usek 
b:=1
i:=L
j:=M+1 // pomocne indexy
while (i <= M) or (j <= R) do   // existuje nezpracovany prvek 
  if (i <= M) and (j <= R) then // oba useky neprazdne
    if A[i] <= A[j] then
      B[b]:=A[i]
      inc(i)
    else
      B[b]:=A[j]
      inc(j)
    inc(b)
  if (i > M) then // prvni usek prazdny
    B[b]:=A[j]     // dojizdime druhy usek
    inc(j)
    inc(b)
  if (j > R) then // druhy usek prazdny
    B[b]:=A[i]     // dojizdime prvni usek
    inc(i)
    inc(b)

Vnější třídění

Pokud máme za úkol setřídit data, která se nám nevejdou do RAM, musíme využít pevný disk, k ukládání mezivýsledků.

Základní postup (idea) jak to udělat je následující:

  1. 1) načteme do paměti kus vstupních posloupnosti
  2. 2) setřídíme ve vnitřní paměti co máme načteno
  3. 3) uložíme na disk setříděný úsek
  4. 4) pokud nejsou zpracována všechna vstupní data do setříděných úseků, vrátíme se do 1)
  5. 5) slejeme postupně všechny setříděné úseky do jednoho

Na výše uvedeném postupu lze mnohé vylepšit. Například můžeme ke třídění použít haldu a prodloužit tak vzniklé předtříděné úseky z bodu 3). Nebo můžeme slévat víc souborů najednou - to si můžeme představit jako víc front, z jejichž začátků vždy vybíráme ten nejmenší prvek.

Domácí úkol

V CodExu je zadána uloha Dodavatel mřížek za 20 bodů.