]> mj.ucw.cz Git - ga.git/blob - 8-qheap/8-qheap.tex
Uvody na zacatku kapitol a ruzne mensi typograficke upravy.
[ga.git] / 8-qheap / 8-qheap.tex
1 \def\msb{{\rm MSB}}
2 \def\rank{{\rm Rank}}
3
4 \def\pnromanp{(\nroman)}
5 \def\pnromanap{(\nroman ')}
6
7 \input ../sgr.tex
8
9 \prednaska{8}{Q-Heaps}{}
10
11 V~minulé kapitole jsme zavedli výpoèetní model RAM a nahlédli jsme,
12 ¾e na~nìm mù¾eme snadno simulovat vektorový poèítaè s~vektorovými operacemi pracujícími v~konstantním èase.
13 Kdy¾ u¾ máme takový poèítaè, pojïme si ukázat, jaké datové struktury na~nìm mù¾eme
14 vytváøet.
15
16 Bez újmy na~obecnosti budeme pøedpokládat, ¾e hodnoty, které do~struktur ukládáme,
17 jsou navzájem rùzné.
18
19 Svým sna¾ením budeme smìøovat ke~strukturám, které zvládnou operace \<Insert> a \<Delete>
20 v~konstantním èase, pøièem¾ bude omezena buïto velikost èísel nebo maximální velikost
21 struktury nebo obojí.
22
23 \s{Znaèení:} $w$~bude v¾dy znaèit ¹íøku slova RAMu a $n$~velikost vstupu algoritmu,
24 v~nìm¾ datovou strukturu vyu¾íváme (tedy speciálnì víme, ¾e $w\ge\log n$).
25
26 \h{Word-Encoded B-Tree}
27
28 Pùjde o~obyèejný B-strom s daty v~listech, ov¹em kódovaný vektorovì. Do~listù
29 stromu budeme ukládat $k$-bitové hodnoty, vnitøní vrcholy budou obsahovat pouze
30 pomocné klíèe a budou mít nejvý¹e $B$ synù. Strom bude mít hloubku~$h$. Hodnoty
31 v¹ech klíèù ve~vrcholu si budeme ukládat jako vektor, ukazatele na~jednotlivé
32 syny jakbysmet.
33
34 Se~stromem zacházíme jako s~klasickým B-stromem, pøitom operace s~vrcholy
35 provádíme vektorovì: vyhledání pozice prvku ve~vektoru pomocí operace \<Rank>,
36 rozdìlení a sluèování vrcholù pomocí bitových posuvù a maskování, to v¹e
37 v~èase $\O(1)$. Stromové operace (\<Find>, \<FindNext>, \<Insert>, \<Delete>, \dots)
38 tedy stihneme v~èase $\O(h)$.
39
40 Zbývá si rozmyslet, co~musí splòovat parametry struktury, aby se v¹echny
41 vektory ve¹ly do~konstantního poètu slov. Kvùli vektorùm klíèù musí platit
42 $Bk=\O(w)$. Jeliko¾ strom má a¾~$B^h$ listù a nejvý¹e tolik vnitøních vrcholù,
43 ukazatele zabírají $\O(h\log B)$ bitù, tak¾e pro vektory ukazatelù potøebujeme,
44 aby bylo $Bh\log B=\O(w)$. Dobrá volba je napøíklad $B=k=\sqrt w$, $h=\O(1)$, èím¾
45 získáme strukturu obsahující $w^{\O(1)}$ prvkù o~$\sqrt w$ bitech pracující
46 v~konstantním èase.
47
48 \h{Q-Heap}
49
50 Pøedchozí struktura má zajímavé vlastnosti, ale èasto je její pou¾ití
51 znemo¾nìno omezením na~velikost èísel. Popí¹eme tedy o~nìco slo¾itìj¹í
52 konstrukci \cite{fw90trans}, která doká¾e toté¾, ale s~a¾ $w$-bitovými èísly.
53 Tato struktura má spí¹e teoretický význam (konstrukce je znaènì komplikovaná
54 a skryté konstanty nemalé), ale pøekvapivì mnoho my¹lenek je pou¾itelných
55 i v~praxi.
56
57 \s{Znaèení:}
58 \itemize\ibull
59 \: $k = \O(w^{1/4})$ -- omezení na~velikost haldy,
60 \: $r\le k$ -- aktuální poèet prvkù v~haldì,
61 \: $X=\{x_1, \ldots, x_r\}$ -- ulo¾ené $w$-bitové prvky, oèíslujeme si je tak, aby $x_1 < \ldots < x_r$,
62 \: $c_i = \msb(x_i \oplus x_{i+1})$ -- nejvy¹¹í bit, na kterém se li¹í $x_i$ a
63 $x_{i+1}$,
64 \: $\rank_X(x)$ -- poèet prvkù mno¾iny~$X$, které jsou men¹í ne¾ $x$
65 (definujeme i~pro $x\not\in X$).
66 \endlist
67
68 \s{Pøedvýpoèet:} Budeme ochotni obìtovat èas $\O(2^{k^4})$ na~pøedvýpoèet.
69 To mù¾e znít hrozivì, ale ve~vìt¹inì aplikací bude $k=\log^{1/4} n$, tak¾e
70 pøedvýpoèet stihneme v~èase $\O(n)$. V~tomto èase mimo jiné stihneme
71 pøedpoèítat tabulku pro libovolnou funkci, která má vstup dlouhý $\O(k^3)$
72 bitù a kterou pro ka¾dý vstup dovedeme vyhodnotit v~polynomiálním èase.
73 Nadále tedy mù¾eme bezpeènì pøedpokládat, ¾e v¹echny takové funkce
74 umíme spoèítat v~konstantním èase.
75
76 \s{Iterování:} V¹imnìte si, ¾e jakmile doká¾eme sestrojit haldu s~$k$ prvky
77 pracující v~konstantním èase, mù¾eme s~konstantním zpomalením sestrojit
78 i haldu s~$k^{\O(1)}$ prvky. Staèí si hodnoty ulo¾it do~listù stromu
79 s~vìtvením $k$ a konstantním poètem hladin a v~ka¾dém vnitøním vrcholu
80 si pamatovat minimum podstromu a Q-Heap s~hodnotami jeho synù. Tak doká¾eme
81 ka¾dé vlo¾ení i odebrání prvku pøevést na~konstantnì mnoho operací s~Q-Heapy.
82
83 \s{Náèrt} fungování Q-Heapu:
84 Nad~prvky $x_1,\ldots,x_r$ sestrojíme trii~$T$ a nevìtvící se cesty zkomprimujeme
85 (nahradíme hranami). Listy trie budou jednotlivá $x_i$, vnitøní vrchol,
86 který le¾í mezi $x_i$ a $x_{i+1}$, bude testovat $c_i$-tý bit èísla.
87 Pokud budeme hledat nìkteré z~$x_i$, tyto vnitøní vrcholy (budeme jim
88 øíkat {\I znaèky}) nás správnì dovedou do~pøíslu¹ného listu. Pokud ale
89 budeme hledat nìjaké jiné~$x$, zavedou nás do~nìjakého na~první pohled
90 nesouvisejícího listu a teprve tam zjistíme, ¾e jsme zabloudili. K~na¹emu
91 pøekvapení v¹ak to, kam jsme se dostali, bude staèit ke~spoèítání ranku
92 prvku a z~rankù u¾ odvodíme i ostatní operace.
93
94 \s{Pøíklad:}
95 \figure{trie.eps}{Trie. Ohodnocení hran je pouze pro názornost -- není
96 souèástí trie.}{\epsfxsize}
97
98 \s{Lemma 1:} $\rank_X(x)$ je urèen jednoznaènì:
99 \numlist\pnromanp
100 \:tvarem stromu $T$,
101 \:indexem $i$ listu $x_i$, do~kterého nás zavede hledání hodnoty~$x$ ve~stromu,
102 \:vztahem mezi $x$ a $x_i$ ($x<x_i$, $x>x_i$ nebo $x=x_i$),
103 \:pozicí $b=\msb(x \oplus x_i)$.
104 \endlist
105
106 \proof Pokud $x=x_i$, je zjevnì $\rank_X(x) = i$. Pøedpokládejme tedy $x\ne x_i$.
107 Hodnoty znaèek klesají ve~smìru od koøene k~listùm a na cestì od koøene k~$x_i$ se
108 v¹echny bity v $x_i$ na~pozicích urèených znaèkami shodují s bity v $x$, pøièem¾
109 a¾ do~pozice $b$ se shodují i bity znaèkami netestované. Sledujme tuto cestu
110 od~koøene a¾ po~$b$: pokud cesta odboèuje doprava, jsou v¹echny hodnoty
111 v~levém podstromu men¹í ne¾~$x$, a~tedy se do~ranku zapoèítají. Pokud odboèuje
112 doleva, jsou hodnoty v~pravém podstromu zaruèenì vìt¹í a nezapoèítají se.
113 Pokud nastala neshoda a $x<x_i$ (tedy $b$-tý bit v~$x$ je nula, zatímco v~$x_i$
114 je jednièkový), jsou v¹echny hodnoty pod touto hranou vìt¹í; pøi opaèné nerovnosti
115 jsou men¹í.
116 \qed
117
118 \s{Pøíklad:} Vezmìme mno¾inu $X=\{x_1,x_2,\ldots,x_6\}$ z pøedchozího pøíkladu
119 a poèítejme $\rank_X(011001)$. Místo první neshody je oznaèeno puntíkem.
120 Platí $x>x_i$, tedy celý podstrom je men¹í ne¾ $x$, proèe¾ $\rank_X(011001)=4$.
121
122 Rádi bychom pøedchozí lemma vyu¾ili k~sestrojení tabulek, které podle uvedených
123 hodnot vrátí rank prvku~$x$. K~tomu potøebujeme pøedev¹ím umìt indexovat tvarem
124 stromu.
125
126 \s{Pozorování:} Tvar trie je jednoznaènì urèen hodnotami $c_1,\ldots,c_n$
127 (je to toti¾ kartézský strom nad tìmito hodnotami -- blí¾e viz kapitola o~dekompozicích
128 stromù), hodnoty v~listech jsou $x_1,\ldots,x_n$ v~poøadí zleva doprava.
129
130 Vektor $(c_1,\ldots,c_n)$ má pouze $k\log w=\O(k^2)$ bitù, tak¾e jím mù¾eme
131 indexovat. Pro zjednodu¹ení ostatních operací ale zvolíme trochu jinou,
132 ekvivalentní reprezentaci:
133
134 \s{Znaèení:}
135 \itemize\ibull
136 \:$B := \{c_1,\ldots,c_r\}$ (mno¾ina v¹ech pozic bitù, které trie testuje, ulo¾ená ve~vektoru setøídìnì)
137 \:$C: \{1,\ldots,r\} \to B: B[C(i)]=c_i$.
138 \endlist
139
140 \s{Lemma 1':} $\rank_X(x)$ lze spoèítat v~konstantním èase~z:
141 \numlist\pnromanap
142 \:funkce $C$,
143 \:hodnot $x_1,\ldots,x_r$,
144 \:$x[B]$ -- hodnot bitù na~\uv{zajímavých} pozicích v~èísle~$x$.
145 \endlist
146
147 \proof Z~pøedchozího lemmatu:
148 \numlist\pnromanp
149 \:Tvar stromu závisí jen na~nerovnostech mezi polohami znaèek,
150   tak¾e je jednoznaènì urèený funkcí~$C$.
151 \:Z~tvaru stromu a $x[B]$ jednoznaènì plyne list $x_i$ a tyto vstupy
152   jsou dostateènì krátké na~to, abychom mohli pøedpoèítat tabulku
153   pro prùchod stromem.
154 \:Zjistíme prostým porovnáním.
155 \:$x_i$ známe a MSB umíme na~RAMu poèítat v~konstantním èase.
156 \endlist
157 Pøitom (i)--(iv) jsou opìt dost krátké na~to, abychom jimi mohli
158 indexovat tabulku.
159 \qed
160
161 \>Poèítání rankù je témìø v¹e, co potøebujeme k~implementaci operací
162 \<Find>, \<Insert> a \<Delete>. Jedinou dal¹í pøeká¾ku tvoøí zatøiïování
163 do~seznamu $x_1,\ldots,x_r$, který je moc velký na~to, aby se ve¹el
164 do~$\O(1)$ slov. Proto si budeme pamatovat zvlá¹» hodnoty v~libovolném
165 poøadí a zvlá¹» permutaci, která je setøídí -- ta se ji¾ do~vektoru vejde.
166 Øeknìme tedy poøádnì, co~v¹e si bude struktura pamatovat:
167
168 \s{Stav struktury:}
169 \itemize\ibull
170 \:$k$, $r$ -- kapacita haldy a aktuální poèet prvkù (èísla),
171 \:$X=\{x_1,\ldots,x_r\}$ -- hodnoty prvkù v libovolném poøadí (pole èísel),
172 \:$\varrho$ -- permutace na~$\{1,\ldots,r\}$ taková, ¾e $x_i=X[\varrho(i)]$
173   a $x_1<x_2<\ldots<x_r$ (vektor o~$r\cdot\log r$ bitech),
174 \:$B$ -- mno¾ina \uv{zajímavých} bitových pozic (setøídìný vektor o~$r\cdot\log w$ bitech),
175 \:$C$ -- funkce popisující znaèky: $c_i=B[C(i)]$ (vektor o~$r\cdot\log r$ bitech),
176 \:pøedpoèítané tabulky pro rùzné funkce.
177 \endlist
178
179 \>Nyní ji¾ uká¾eme, jak provádìt jednotlivé operace:
180
181 \>$\<Find>(x):$
182
183 \algo
184 \:$i := \rank_X(x)$.
185 \:Pokud $x_i=x$, odpovíme {\sc ano,} jinak {\sc ne.}
186 \endalgo
187
188 \>$\<Insert>(x):$
189
190 \algo
191 \:$i := \rank_X(x)$
192 \:Pokud $x=x_i$, hodnota u¾ je pøítomna.
193 \:Ulo¾íme $x$ do~$X[\mathop{{+}{+}}r]$ a vlo¾íme $r$ na~$i$-té místo v~permutaci~$\varrho$.
194 \:Pøepoèítáme $c_{i-1}$ a $c_i$. Pro ka¾dou zmìnu $c_j$:
195 \::Pokud je¹tì nová hodnota není v~$B$, pøidáme ji tam.
196 \::Upravíme $C(j)$, aby ukazovalo na~tuto hodnotu.
197 \::Pokud se na~starou hodnotu neodkazuje ¾ádné jiné $C(\cdot)$, sma¾eme ji z~$B$.
198 \endalgo
199
200 \>$\<Delete>(x):$
201
202 \algo
203 \:$i := \rank_X(x)$ (víme, ¾e $x_i=x$).
204 \:Sma¾eme $x_i$ z~pole~$X$ (napøíklad prohozením s~posledním prvkem) a pøíslu¹nì upravíme~$\varrho$.
205 \:Pøepoèítáme $c_{i-1}$ a $c_i$ a upravíme $B$ a $C$ jako pøi Insertu.
206 \endalgo
207
208 \s{Èasová slo¾itost:} V¹echny kroky operací po~výpoètu ranku trvají konstantní èas, rank
209 samotný zvládneme spoèítat v~$\O(1)$ pomocí tabulek, pokud známe $x[B]$. Zde je ov¹em
210 nalíèen háèek -- tuto operaci nelze na~Word-RAMu konstantním poètem instrukcí spoèítat.
211 Jak si pomù¾eme:
212
213 \itemize\ibull
214 \:Vyu¾ijeme toho, ¾e operace $x[B]$ je v~${\rm AC}^0$ a vystaèíme si se strukturou pro ${\rm AC}^0$-RAM.
215 Zde dokonce mù¾eme vytváøet haldy velikosti a¾ $w\log w$. Také pøi praktické implementaci mù¾eme vyu¾ít
216 toho, ¾e souèasné procesory mají instrukce na~spoustu zajímavých ${\rm AC}^0$-operací, viz napø. pìkný
217 rozbor v \cite{thorup:ac0}.
218 \:Jeliko¾ $B$ se pøi jedné Q-Heapové operaci mìní pouze o~konstantní poèet prvkù, mù¾eme
219 si udr¾ovat pomocné struktury, které budeme umìt pøi lokální zmìnì~$B$ v~lineárním èase
220 pøepoèítat a pak pomocí nich indexovat. To pomocí Word-RAMu lze zaøídit, ale je to technicky
221 dosti nároèné, tak¾e ètenáøe odkazujeme na~Fredmanùv a Willardùv èlánek \cite{fw90trans}.
222 \endlist
223
224 \h{Aplikace Q-Heapù}
225
226 Jedním velice pìkným dùsledkem existence Q-Heapù je lineární algoritmus na~nalezení
227 minimální kostry grafu ohodnoceného celými èísly. Získáme ho z~Fredmanovy a Tarjanovy
228 varianty Jarníkova algoritmu (viz kapitoly o~kostrách) tak, ¾e v~první iteraci pou¾ijeme
229 jako haldu Q-Heap velikosti $\log^{1/4} n$ a pak u¾ budeme pokraèovat s~Fibonacciho
230 haldou. Tak provedeme tolik prùchodù, kolikrát je potøeba zlogaritmovat $n$,
231 aby výsledek klesl pod~$\log^{1/4} n$, a~to je konstanta. V¹imnìte si, ¾e by nám
232 dokonce staèila halda velikosti $\O(\log^{(k)} n)$ a~operacemi v~konstantím èase
233 pro nìjaké libovolné~$k$.
234
235 \references
236 \bye