From: Martin Mares Date: Sun, 2 Sep 2007 21:16:03 +0000 (+0200) Subject: Nova verze prednasky o QuickSortu s peknymi obrazky. X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=ad870868b3094381855ab6351677d3fcab7e4e64;p=ads1.git Nova verze prednasky o QuickSortu s peknymi obrazky. --- diff --git a/5-qs/5-qs.tex b/5-qs/5-qs.tex index 7a14e59..6c95600 100644 --- a/5-qs/5-qs.tex +++ b/5-qs/5-qs.tex @@ -1,13 +1,12 @@ \input ../lecnotes.tex -\prednaska{5}{QuickSort a slo¾itost tøídìní}{(Michal Sta¹a, ???)} +\prednaska{5}{QuickSort a slo¾itost tøídìní}{(Michal Sta¹a, Jan Návrat)} Dostaneme posloupnost, její¾ prvky dovedeme porovnávat, a sna¾íme se co nejefektivnìji posloupnost setøídit. Uká¾eme si tøídící algoritmus QuickSort -(pro pøátele QS) zalo¾ený na metodì Rozdìl a panuj: +(pro pøátele QSort nebo QS) zalo¾ený na metodì Rozdìl a panuj: \s{Algoritmus:} (QuickSort) - \def\concat{\mathop{\hbox{.}}} \algo @@ -21,121 +20,117 @@ nejefektivn \s{Rozbor:} V¹imnìme si, ¾e QS se urèitì zastaví a také ¾e vydá -správný výsledek. To mù¾eme ovìøit napø. indukcí podle $\vert X\vert$. +správný výsledek. To mù¾eme ovìøit napøíklad indukcí podle $\vert X\vert$. -Podobnì jako u~vybírání $k$-tého nejmen¹ího prvku v~minulých pøedná¹kách -i zde èasová slo¾itost závisí hlavnì na~volbì pivota. Kdybychom za~pivota -zvolili medián, vy¹la by èasová slo¾itost stejnì jako u~MergeSortu: +Podobnì jako u vybírání $k$-tého nejmen¹ího prvku v minulých pøedná¹kách +i zde èasová slo¾itost závisí hlavnì na volbì pivota. Kdybychom za pivota +zvolili medián, vy¹la by èasová slo¾itost stejnì jako u MergeSortu: $$ T(n) = 2T(n/2) + O(n) = O(n\log n). $$ Pokud naopak budeme volit pivota ne¹ikovnì, dostaneme: $$ T(n) = T(n - 1) + \Theta(n) = \Theta(n^2). $$ V ideálním pøípadì bychom tedy chtìli za pivota zvolit medián, av¹ak jeho pøímým výpoètem bychom algoritmus pøíli¹ zpomalili. Pou¾ívá se proto mnoho zpùsobù, jak vybrat rychle pivota blízkého mediánu. -Èasto pou¾ívanou metodou je náhodný výbìr, v~praxi realizovaný nìjakým pseudonáhodným -generátorem. Uká¾eme, ¾e v~tomto pøípadì je QS v~prùmìrném pøípadì rychlý: +Èasto pou¾ívanou metodou je náhodný výbìr, v praxi realizovaný nìjakým pseudonáhodným +generátorem. Uká¾eme, ¾e v tomto pøípadì je QS v prùmìrném pøípadì rychlý: -\s{Vìta:} QS s~náhodnou volbou pivota má èasovou slo¾itost v~prùmìru -$\O(n\log n)$. +\s{Vìta:} QS s náhodnou volbou pivota má èasovou slo¾itost v prùmìru $\O(n\log n)$. -\s{Poznámka:} Stejnì jako u~výbìru $k$-tého nejmen¹ího prvku bychom také -mohli ukázat, ¾e QS s~pevnou volbou pivota spu¹tìný na~náhodnou permutaci +\s{Poznámka:} Stejnì jako u výbìru $k$-tého nejmen¹ího prvku bychom také +mohli ukázat, ¾e QS s pevnou volbou pivota spu¹tìný na náhodnou permutaci má tuté¾ èasovou slo¾itost. Detaily nicménì vynecháme. \noindent {\sl Dùkaz vìty:} -Rozdìlíme bìh algoritmu na~fáze, pøièem¾ fází rozumíme cestu ve~stromu volání, +Dùkaz provádíme rozdìlením algoritmu na fáze. +Rekurzivní volání QSortu zle zobrazit jako¾to strom, pøièem¾ fází rozumíme cestu ve stromu volání, která sleduje vìt¹í díl a konèí, kdy¾ se povede vybrat za pivota l¾imedián. \figure{strom-dukaz.eps}{Dùkaz rozdìlením na fáze}{0.3\hsize} -Ka¾dá fáze pøitom rozdìlí vstup na~disjunktní èásti $X_1, \ldots, X_k$ ($k\ge 2$) -a pivoty, kteøí je oddìlují. Proto je $\sum_i n_i \leq n$, -kde $n$ znaèí velikost vstupu a~$n_i$ velikost $i$-té èásti. Velikost ka¾dé -èásti je navíc nejvý¹e $3/4 \cdot n$ (na~konci fáze to platí proto, ¾e jsme -zvolili l¾imedián, pøedtím jsme v¾dy oddìlili men¹í z~èástí, èili nejvý¹e $n/2$). +\figure{Faze.eps}{Fáze}{0.3\hsize} + +Ka¾dá fáze pøitom rozdìlí vstup na disjunktní èásti $X_1, \ldots, X_k$ ($k\ge 2$) +a pivoty, kteøí je oddìlují. +Oznaème si $n$ za velikost vstupu (poèet prvkù vstupní posloupnosti) a $n_i$ za velikost $i$-té èásti. +Nahlédneme, ¾e platí $\sum_i n_i \leq n$. +Velikost ka¾dé èásti je navíc nejvý¹e $3/4 \cdot n$ (na konci fáze to platí proto, ¾e jsme +zvolili l¾imedián, pøedtím jsme v¾dy oddìlili men¹í z èástí, èili nejvý¹e $n/2$). -Jedna iterace algoritmu trvá~$\O(n)$ a jeliko¾ l¾imedián vybereme s~pravdìpodobností alespoò $1/2$, -je v~jedné fázi v~prùmìru $\O(1)$ iterací a celá fáze proto v~prùmìru trvá èas~$\O(n)$. -Z~toho dostaneme následující rekurenci pro prùmìrnou èasovou slo¾itost celého algoritmu: +Jedna iterace algoritmu trvá $\O(n)$ a jeliko¾ l¾imedián vybereme s pravdìpodobností alespoò $1/2$, +je v jedné fázi v prùmìru $\O(1)$ iterací a celá fáze proto v prùmìru trvá èas $\O(n)$. +Z toho dostaneme následující rekurenci pro prùmìrnou èasovou slo¾itost celého algoritmu: $${\bb E}T(n) = \sum_i {\bb E}T (n_i) + \O(n).$$ -Tento typ rekurence jsme je¹tì nepotkali a Kuchaøková vìta na~ni nezabere, -ov¹em mù¾eme si pomoci jednoduchou úvahou. Pøedstavme si, ¾e v~na¹em stromu -rekurzivních volání zkomprimujeme ka¾dou fázi do~jednoho vrcholu. Tím vznikne -strom, který odpovídá algoritmu, jen¾ v~jedné iteraci v~prùmìrnì lineárním -èase rozdìlí vstup na~nìkolik èástí a rekurzivnì se na~nì zavolá. +Tento typ rekurence jsme je¹tì nepotkali a Kuchaøková vìta\foot{MasterTheorem} na ni nezabere, +ov¹em mù¾eme si pomoci jednoduchou úvahou. Pøedstavme si, ¾e v na¹em stromu +rekurzivních volání zkomprimujeme ka¾dou fázi do jednoho vrcholu. Tím vznikne +strom, který odpovídá algoritmu, jen¾ v jedné iteraci v prùmìrnì lineárním +èase rozdìlí vstup na nìkolik èástí a rekurzivnì se na nì zavolá. + +\figure{KomprimovanyStrom.eps}{Komprimovaný Strom}{0.3\hsize} -\s{FIXME:} Obrázek +\figure{Komprimace.eps}{Zpùsob vytvoøení komprimovaného stromu}{0.3\hsize} -Nový strom má logaritmickou hloubku, proto¾e na~ka¾dé dal¹í hladinì jsou -délky posloupností nejvý¹e $3/4$ délek z~pøedchozí hladiny. Navíc souèet -délek pøes ka¾dou hladinu je maximálnì~$n$. Proto na~ka¾dé hladinì -trávíme èas v~prùmìru $\O(n)$ a v~celém stromu tedy $\O(n\log n)$. +Nový strom má logaritmickou hloubku, proto¾e na ka¾dé dal¹í hladinì jsou +délky posloupností nejvý¹e $3/4$ délek z pøedchozí hladiny. Navíc souèet +délek pøes ka¾dou hladinu je maximálnì $n$. Proto na ka¾dé hladinì +trávíme èas v prùmìru $\O(n)$ a v celém stromu tedy $\O(n\log n)$. \qed \s{Pozorování:} Na¹e první verze QS spotøebuje lineární mno¾ství pamìti -na~pomocné pole a na~zásobník. Na~pøedná¹ce jsme ukazovali rùzná jeho -praktická vylep¹ení, které staèí pomocná pamì» o~velikosti $\O(\log n)$. +na pomocné pole a na zásobník. Na pøedná¹ce jsme ukazovali rùzná jeho +praktická vylep¹ení, které staèí pomocná pamì» o velikosti $\O(\log n)$. Detaily viz webové stránky pøedná¹ky. -Známe u¾ nìkolik tøídících algoritmù s~èasovou slo¾itostí $\O(n\log n)$. -Následující vìta ukazuje, ¾e efektivnìj¹í algoritmus v~obecném pøípadì +Známe u¾ nìkolik tøídících algoritmù s èasovou slo¾itostí $\O(n\log n)$. +Následující vìta ukazuje, ¾e efektivnìj¹í algoritmus v obecném pøípadì nese¾eneme. \s{Vìta:} Ka¾dý tøídící algoritmus zalo¾ený na porovnávání a prohazování prvkù -potøebuje na~vstup délky~$n$ v~nejhor¹ím pøípadì $\Omega (n \log n)$ porovnání. +potøebuje na vstup délky $n$ v nejhor¹ím pøípadì $\Omega (n \log n)$ porovnání. \proof -\itemize\ibull - \:BÚNO nejdøíve algoritmus porovnává a potom - prohazuje (algoritmus mù¾eme upravit tak, aby si pamatoval - aktuální permutaci prvkù a podle ní prohazoval a¾ na~konci). - - \:BÚNO je vstup algoritmu permutace na~mno¾inì $\{1, \ldots, n\}$. - - \:Chování algoritmu popí¹eme rozhodovacím stromem. Jeho vnitøní vrcholy - urèují jednotlivá porovnání prvkù, listy odpovídají okam¾ikùm, kdy - algoritmus pøestal porovnávat a zaèal prohazovat. - -\s{FIXME: Obrázek} - - \:V¹imneme si, ¾e nemohou existovat dvì vstupní permutace, pro které - by algoritmus skonèil v~tém¾e listu rozhodovacího stromu, jeliko¾ - v~okam¾iku, kdy algoritmus dorazí do~listu, nemù¾e u¾ získávat - ¾ádné informace o~vstupu a ¾ádná posloupnost prohození nemù¾e - setøídit jak první, tak druhou permutaci. Listù stromu je tedy - alespoò tolik, kolik je rùzných vstupù, tedy~$n!$. - -{\parindent=\leftskip\narrower - \s{Lemmátko:} Binární strom hloubky~$k$ má nejvý¹e $\leq 2^k$ listù. - \par\noindent {\sl Dùkazík:} Uva¾me binární strom hloubky $k$ s~maximálním poètem - listù. V~takovém stromu budou v¹echny listy urèitì le¾et na~poslední hladinì - (kdyby nele¾ely, mù¾eme pod nìkterý list na~vy¹¹í hladinì pøidat dal¹í dva vrcholy a získat - tak \uv{listnatìj¹í} strom stejné hloubky). Jeliko¾ na~$i$-té hladinì je nejvý¹e $2^i$ - vrcholù, v¹ech listù je nejvý¹e~$2^k$. +Bez újmy na obecnosti budeme nejdøíve pøedpokládat o algoritmu dvì vìci: +Jednak to, ¾e algoritmus nejprve porovnává, a teprve potom prohazuje.\foot{Algoritmus +mù¾eme upravit tak, aby si pamatoval aktuální permutaci prvkù a podle ní prohazoval a¾ na konci.} +Také pøedpokládáme, ¾e vstup algoritmu je permutace na mno¾inì $\{1, \ldots, n\}$. + +Chování tohoto algoritmu popí¹eme rozhodovacím stromem. V rozhodovacím stromu vnitøní vrcholy +urèují jednotlivá porovnání prvkù a listy odpovídají okam¾ikùm, kdy algoritmus pøestal porovnávat a zaèal prohazovat. + +\figure{RozhodovaciStrom.eps}{Rozhodovací Strom}{0.3\hsize} + +Vstup je tedy permutace $n$ prvkù, a víme ¾e poèet rùzných permutací je $n!$. Existuje tedy právì $n!$ rùzných vstupù. +Dále si v¹imneme, ¾e nemohou existovat dvì vstupní permutace, pro které by algoritmus skonèil v tém¾e listu rozhodovacího stromu. +Listù stromu je tedy alespoò tolik, kolik je rùzných vstupù, tedy $n!$. + +{\narrower + \s{Lemmátko:} Binární strom hloubky $k$ má nejvý¹e $2^k$ listù. + \par\noindent {\sl Dùkazík:} Uva¾me binární strom hloubky $k$ s maximálním poètem + listù. V takovém stromu budou v¹echny listy urèitì le¾et na poslední hladinì + (kdyby nele¾ely, mù¾eme pod nìkterý list na vy¹¹í hladinì pøidat dal¹í dva vrcholy a získat + tak \uv{listnatìj¹í} strom stejné hloubky). Jeliko¾ na $i$-té hladinì je nejvý¹e $2^i$ + vrcholù, v¹ech listù je nejvý¹e $2^k$. \qed - } - Z~tohoto lemmátka plyne, ¾e rozhodovací strom musí být hluboký alespoò - $\log n!$. +\>Z~tohoto lemmátka plyne, ¾e rozhodovací strom musí být hluboký alespoò $\log n!$. - \:Zbytek je u¾ snadné cvièení z~diskrétní matematiky: +\>Zbytek je u¾ snadné cvièení z diskrétní matematiky: -{\parindent=\leftskip\narrower - \s{Lemmátko:} $ n! \ge n^{n / 2} $. +{\narrower + \s{Lemmátko:} $ n! \ge n^{n / 2}$. \par\noindent {\sl Dùkazík:} $n! = \sqrt{(n!)^2} = \sqrt{1(n-1)\cdot 2(n-2) \cdot \ldots \cdot n\cdot 1}$, co¾ mù¾eme také zapsat jako $\sqrt{1(n-1)}\cdot \sqrt{2(n-2)} \cdot \ldots \cdot \sqrt{n\cdot 1}$. Pøitom pro ka¾dé $1\le k\le n$ je $k(n+1-k) = kn + k - k^2 = n + (k-1)n + k(1-k) = n + (k-1)(n-k) \ge n$. Proto je ka¾dá z~odmocnin vìt¹í nebo rovna $n^{1/2}$ a $n!\ge (n^{1/2})^n = n^{n/2}$. \qed - } - Hloubka stromu tedy èiní minimálnì $\log n! \ge \log(n^{n/2}) = n/2 \cdot \log n = \Omega(n\log n)$, - co¾ také zdola odhaduje poèet porovnání, který algoritmus provede v~nejhor¹ím pøípadì. +\>Hloubka stromu tedy èiní minimálnì $\log n! \ge \log(n^{n/2}) = n/2 \cdot \log n = \Omega(n\log n)$, +co¾ také zdola odhaduje poèet porovnání, který algoritmus provede v nejhor¹ím pøípadì. \qed \bye diff --git a/5-qs/Faze.eps b/5-qs/Faze.eps new file mode 100644 index 0000000..cb7e7b6 Binary files /dev/null and b/5-qs/Faze.eps differ diff --git a/5-qs/Komprimace.eps b/5-qs/Komprimace.eps new file mode 100644 index 0000000..37a755d Binary files /dev/null and b/5-qs/Komprimace.eps differ diff --git a/5-qs/KomprimovanyStrom.eps b/5-qs/KomprimovanyStrom.eps new file mode 100644 index 0000000..773ab1f Binary files /dev/null and b/5-qs/KomprimovanyStrom.eps differ diff --git a/5-qs/RozhodovaciStrom.eps b/5-qs/RozhodovaciStrom.eps new file mode 100644 index 0000000..e4e3f76 Binary files /dev/null and b/5-qs/RozhodovaciStrom.eps differ