{{TIN066 Skripta}}
Bucket sort
Mějme n prvků v rozsahu 0..m; připravíme si m+1 množin a do každé rozházíme prvky se stejným číslem, množiny pak spojíme za sebe a máme výsledek. Třídění zachovává pořadí.
Pro inicializiaci potřebujeme O(m), pro rozházení O(n), pro konkatenaci ideálně zase O(m), takže celkem třídění zabere O(m+n) času.
Hybrid sort
Bucketsort umí jen přirozená čísla a potřebuje hodně přihrádek; zkusme zmenšit počet přihrádek, klidně mít více prvků v jedné, ale zachovat očekávanou lineární složitost.
Mějme zase n prvků, tentokrát z
ParseError: KaTeX parse error: Undefined control sequence: \[ at position 1: \̲[̲0,1]
, a danépočet přihrádek bude
Ale co v průměru (pro rovnoměrně rozdělený vstup)? Velikosti přihrádek se řídí binomickým pravděpodobnostním rozdělením s parametrem p=1/k. (Binomické rozdělení popisuje pravděpodobnost, že při a hodech mincí (jeden hod má pravděpodobnost právě parametr p) se jich b povede. Pravděpodobnost, že mince spadne do naší přihrádky, je 1/k.)
Jedno přidání do přihrádky velikosti
Střední hodnota velikosti přihrádky i je v binomickém rozdělení
Word sort
Chceme třídit větší objekty než jen přihrádkovatelná čísla - slova (často se teprve tomuto algoritmu říká bucketsort nebo radixsort). Mějme úplně uspořádanou abecedu, chceme lexikograficky setřídit různě dlouhá slova
Jaká je idea? (Chvíle googlení. Chvíle čtení fór. Chvíle zoufalství. Přišla chvíle zalistovat ve Knuthov!) Představme si balíček karet, který chceme setřídit (primárně dle barvy, sekundárně dle hodnoty). Můžeme na to jít mnoha způsoby, ale šikovné je si nejdříve udělat hromádku pro každou hodnotu, rozházet karty a položit hromádky na sebe ve správném pořadí. V druhém průchodu si zase uděláme hromádku pro každou barvu, znovu rozházíme karty a hromádky zpátky položíme na sebe. A... a je to! Díky tomu, že bucketsort je stabilní, máme balíček správně setříděný. Pro slova delší než 2 iterujeme vícekrát.
To je fajn, ale máme problém, slova totiž mohou být různě dlouhá. Díky tomu se nám algoritmus zkomplikuje, když se ale rozumně vyloží ve správném pořadí (což se zatím kdovíproč dařilo málokomu), je z něj ta idea stále vidět.
Mějme množinu slov, nejdříve si ji rozdělme bucketsortem do přihrádek dle délky. Výstupní množina T bude na začátku prázdná. Postupně budujme množinu slov T od nejdelších k nejkratším; v každé iteraci snížíme limit i na délku slova, na začátek množiny T přidáme nově povolená slova, a bucketsortem setřídíme T podle i-tého písmenka (díky jeho stabilitě jsme tím nerozbili setřídění z předchozích iterací). V poslední iteraci skončíme s T obsahující setříděná všechna slova. Lze snadno nahlédnout, že kdyby měla všechna slova stejnou délku, bude to přesně náš karetní algoritmus.
No jo, ale tohle nebude moc efektivní - řekli jsme, že bucketsortem setřídíme T, ale to znamená vždy při výstavbě nové verze T projít n přihrádek pro celou abecedu, takže složitost hlavního cyklu bude nějaká ošklivá - možná třeba (bez záruky) O(l*(m + n)) (kde n je velikost abecedy, m je počet slov a l je délka nejdelšího - l-krát otočím hlavní cyklus, zpracuju až m slov, a zkonkatenuju obsah n přihrádek); respektive přesněji O(L + l*n) (L je součet délek všech slov). Bylo by hezké, abychom vždy procházeli jen přihrádky, ve kterých něco je.
Tak uděláme další preprocessing! Rozdrobíme slova na "písmenka se souřadnicemi"
Složitost
V následujícím značíme
Preprocessing - vytvoření dvojic
Vlastní algoritmus - rozhození podle délek slov trvá
Složitost celého algoritmu pak bude Složitost preprocessingu + Složitost samotného třídění
(IMHO je v běžném případě ten preprocessing málo muziky za hodně peněz, ale máme-li velikou abecedu nebo dlouhatánská slova...)