Přihrádkové třídění řetězců
Transkript
Přihrádkové třídění řetězců Aleš Novák, ADS I., 30.6.2011 Ke třídění množiny prvků, které nabývají hodnot převoditelných na přirozená čísla v omezeném, „rozumnémÿ rozsahu, můžeme použít přihrádkové třídění – bucketsort. Bucketsort prochází vstupní množinu a spočítá pro každou podmnožinu prvků stejné hodnoty „přihrádkuÿ ve výstupním, již setříděném poli. Máme-li N prvků o rozsahu 0 . . . R ve vstupním poli „vstupÿ, algoritmus v pseudo-C kódu vypadá takto: 1: vstup [1..N], vysledek [1..N], prihradky [0..R+1] 2: prihradky = [0,0,0..0] 3: for i in 1..N: 4: prihradky [vstup [i] + 1] ++ 5: prihradky [0] = 0 6: for r in 1..R: 7: prihradky [r] += prihradky [r-1] 8: for i in 1..N: 9: vysledek [prihradky [vstup [i]]++] = vstup [i] Vidíme, že používáme ještě jedno pole velikosti N pro výstup a pole četností prvků dané hodnoty o velikosti R. Podle limitů cyklů je vidět časová složitost O(N + R). Cyklus na řádcích 3–4 počítá četnost jednotlivých hodnot prvků. Cyklus na řádcích 5–7 četnost hodnoty prvku nahrazuje sumou četností prvků s menší hodnotou, tím se z údaje „kolikrát se prvek s bezprostředně nižší hodnotou vyskytuje ve vstupním poliÿ stane údaj „kde začíná přihrádka prvků s touto hodnotou ve výstupním poliÿ. V posledním cyklu procházíme vstupní pole zepředu a přihrádky plníme také zepředu, takže vzájemné pořadí prvků stejné hodnoty se nemění – třídění je stabilní. Poznámka: někde (např. ve zbytku tohoto textu a v ukázkovém C programu) je použita podoba algoritmu, která místo začátků počítá konce přihrádek a plní je pak odzadu. Na složitost algoritmu to nemá vliv. Třídění řetězců Pokud máme třídit množinu řetězců, složených z L prvků – znaků, jejichž hodnoty mají „rozumnýÿ rozsah, bychom mohli využít toho, že bucketsort je stabilní, a setřídit řetězce nejprve podle nejméně významného, tj. L-tého znaku, pak podle (L − 1)-tého až nakonec podle 1. znaku, který je nejvýznamnější. Každý znak by se prošel právě jednou, časová složitost je tedy jako při provedení L samostatných bucketsortů - O(L · (N + R)). Pokud ale řetězce nabývají délek 1 . . . L, je situace mírně komplikovanější. Pokud bychom všechny řetězce zarovnali „mezeramiÿ na délku L a použili algoritmus z předchozího odstavce, může být časová složitost až O(N 2 ) (pokud budememe mít N − 1 řetězců délky 1 a jeden délky N ). Tj. většinu času strávíme počítáním četnosti mezer. Jak to udělat s lineární časovou složitostí? Budeme opět porovnávat od nejméně významného, L-tého znaku - ovšem jen u těch řetězců, které mají alespoň L znaků. Pro ten účel nejprve vstupní množinu rozdělíme bucketsortem na podmnožiny Pi , kde množina Pi obsahuje znaky délky i, budeme postupovat od největšího i k nejmenšímu a postupně vytvářet výstupní pole. Po kroku pro přihrádku Pi bude dočasná výstupní množina obsahovat všechny řetězce délky minimálně i setříděné podle i, i + 1, i + 2, ..., L znaku. Postup v pseudo-pseudo kódu bude takovýto: 1: vstup [1..N], vysledek [1..N], prihradky [0..R], vstup_dle_delek [1..N], prihradky_delek [1..L], vysledek_docasny [1..N] 2: prihradky_delek = [0,0,0..0] 3: for i in 1..N: 4: prihradky_delek [delka (vstup[i]) ++ 5: for k in 2..L: 6: prihradky_delek [k] += prihradky_delek [k-1] 7: for i in N..1: 8: vstup_dle_delek [-- prihradky_delek [vstup [i]]] = vstup [i] 9: vysledek = [] 10: k = L 11: while k > 0: 12: vysledek = concat ( vstup_dle_delek [prihradky_delek[k-1]..prihradky_delek [k]], vysledek) 13: prihradky = [0,0,0..0] 14: 15: for i in 1..delka (vysledek): prihradky [vysledek [i][k]] ++ 16: 17: for r in 1..R: prihradky [r] += prihradky [r-1] 18: 19: for i in N..1: vysledek_docasny [-- prihradky [vysledek [i]]] = vysledek [i] 20: 21: vysledek = vysledek_docasny k -- Vidíme, že třídění provádíme L-krát, každý znak v každém řetězci se prochází právě jednou, časová PN složitost je O(RL + i delka(vstup[i])), tedy je lineární s celkovým počtem znaků všech řetězců. Paměťová náročnost je N + R + L, takže je třeba zaručit, že také maximální délka řetězce bude „rozumnáÿ. Správnost algoritmu nahlédneme indukcí - tvrdíme, že po i-tém kroku je dočasná výstupní množina setříděná podle znaku (L − i + 1) až L. Po prvním kroku to je triviálně vidět, protože dočasná výstupní množina obsahuje pouze řetězce z PL , setříděné podle L. znaku. Při i-tém kroku se před dočasný výstupní seznam připojí množina PL−i+1 a dohromady se třídí podle (L − i + 1)- tého znaku. Pokud dva řetězce mají hodnotu znaku stejnou, zachovává se jejich vzájemné pořadí (bucketsort je stabilní), takže se udržuje jejich slovníkové uspořádání z přechozího kroku. Pokud je některý z nich z množiny PL−i+1 , je správně umístěn více vepředu, protože ve slovníkovém uspořádání řetězec ABC předchází řetězci ABCD. Přikládám ukázkové řešení v jazyce C. Použil jsem dvě pole velikosti N , která prohazuji, jedno vždy obsahuje dočasně setříděnou množinu řetězců délky k + 1, do druhého pole jde setříděné zřetězení množiny Pk a množiny z prvního pole. Je třeba zřetězovat je v tomto pořadí (protože řetězec ABC má ve výstupu předcházet řetězci ABCD). Ukázkový postup algoritmu Nakonec uvádím ukázku třídění řetězců: abc, andalusan, b, cadmium, calcium, dac, kleptoman, zetor, zita. Každá dvojice tabulek představuje jeden krok algoritmu. Levá tabulka obsahuje vstupní množiny, dvojitá čára odděluje množinu PL+1−i pro i-tý krok nahoře, dočasný výsledek dole. Pravá tabulka obsahuje dočasný výsledek po konci kroku. Podbarvené jsou znaky, podle kterých se setřiďuje. a k n l d e a p l t u o s m a k n l d e a p l t u o s m c c a k a a n l l d d e c m a p i i l t u u u o c c k a a a l n l d e d c m p a i i t l z k c c a e l a a n t e l d d o p c m a z c c a z k i a a n e l t l d d t e a c m a o p i i l r t n n a a m m s m u u o u r t i i l a a m m m s a a a a a a k n l d e a p l t u o s m n n a k n l d e a p l t u o s m n n c c k a a a l n l d e d c m p a i i t l u u o u n n k c c a l a a n e l d d p c m a t i i l c c a z k a a n e l l d d t e c m a o p z a c c z k i n a a e l t d l d t e o u u u m m m s u u u m m s a n o m a n a n n a a c m o p l i i r t n n a a m m m s o u u u i i l r t a a m m m s n n a a n n a n a n u u u m m s a n o m a n u u u s m m a n o m a n d a z a c c z k d a a c k c z z a b i n a a e l c c t d l d t e a b n a l a i e c c d d e l t t a a c m o p a m p c a o l i i r t l i t i u u u s m m a o m a u u o u s m m m n n a n a n r b d c c a z z k a a a a b e i l n c d l c t t e d m c i i o a p a r t l u u m m o u m s a a n n d a a c k c z z d c c a z z k a a a b c c d k z z a b n a l a i e c c d d e l t t a a a b e i l n c d l c t t e d b n c d a a a l e i d l c e t t a m p c a o l i t i u u o u s m m m a n a n m c i i u u m m o a p a r t l o u m s a a n n a l u s a n m c i i u u m m p o a t r o m a n r Reference [1] Zápisy z ADS I. - Martin Mareš http://mj.ucw.cz/vyuka/1011/ads1/ [2] Přihrádkové třídění - Tomáš Slavíček http://www.vbnet.cz/
Podobné dokumenty
Kuřecí prsa po francouzsku - Úvod
Petrželku omyjeme a osušíme, zbavíme stonků a nasekáme najemno. Česnek oloupeme a
prolisujeme. Vytlačíme si šťávu z půlky citronu a přefiltrujeme ji přes jemné sítko. Parmazán
HelpingPreventCervicalCancer Czech0913
Vakcína proti viru HPV
Vakcína HPV je k dispozici pro dívky ve věku 12 až 13 let
prostřednictvím imunologického programu pro školy. Další informace o
vakcíně naleznete na webové stránce s informace...
Lambda depth-first proof
PN a DN nesmí být nadhodnoceny, jsou to dolní odhady.
Odhad obtížnosti důkazu/vyvrácení uzlu.
Využití doménových heuristik.
Stránka 1 Obj. kód Specifikace MOC MOC
Baterie Nokia 6100, 6300, 2650, 2652, 3500 classic, 5100, 5310, 6101, 6102, 6103,
6104, 6125, 6131, 6136, 6170, 6103, 6170, 6260, 6301, 7200, 7270, E50, E60, NGage, N70, N71, N72, N91, N91 8GB, 110...
Úvod do Programování
je, že není takzvaně case-sensitive, čili nerozlišuje velká a malá písmena.
Napsali jsme dva příkazy (každý příkaz v Pascalu je ukončen středníkem „;ÿ). První příkaz je
WriteLn(’Ahoj!’); Tento přík...
Seznam všech témat pro ústní zkoušku PRG+IDS 2011
• výběry sloupců
• aliasy sloupců a tabulek
• spojování sloupců pomocí fce CONCAT()
• výběry řádků
• změna řazení výpisu řádků
• omezení řádků výpisu
• využití NULL, LIKE
• pohledy
Terminálový vstu...