this dir | view | cards | source | dark
top
Definice algoritmu
Výpočetní model RAM
- obvyklý pseudokód
- paměť tvoří proměnné a pole
- aritmetické operace konstantní, ale
- všechny problémy jdou vyřešit v konstantním čase magií s čísly
- aritmetické operace trvají log. k délce čísel
- velikost čísel omezena velikostí slova w, adresy mají délku w, máme k dispozici 2w paměti
Čas a prostor konkrétního výpočtu
- součet cen provedených instrukcí, vzdálenost maximální a minimální adresy
Časová a prostorová složitost
- maximální čas a prostor pro vstup dané délky
Asymptotická notace: O, Ω, Θ
- f∈O(g)⇔∃c:∀n>ε:f(n)<c⋅g(n)
- f∈Ω(g)⇔∃c:∀n>ε:f(n)>c⋅g(n)
- f∈Θ(g)⇔f∈O(g)\andf∈Ω(g)
Základní grafové algoritmy
Prohledávání do šířky (BFS)
- nalezené nenavštívené vrcholy ukládám do fronty.
- procházíme po vrstvách
- existují pouze stromové, příčné a dopředné hrany, dopředné pouze do následující vrstvy
Prohledávání do hloubky (DFS)
- zásobník nebo rekurze
- vrcholy neviděné, otevřené, uzavřené
- na konci:
- dosažitelný ⇔ uzavřený
- nedosažitelný ⇔ neviděný
- indukcí podle doby běhu ⇐
- minimální protipříklad ⇒
Klasifikace hran xy v DFS
- stromová -- využili jsme ji během prohledávání (otevřený → neviděný)
- zpětná -- ukazuje do otevřeného vrcholu (otevřený → otevřený)
- dopředná -- x otevřeno před y (otevřený → uzavřený)
- příčná -- x otevřeno až po y (otevřený → uzavřený)
Hledání mostů
- v každém vrcholu si pamatujeme low(v) jako minimum z in(w) pro všechny vrcholy dosažitelné odkudkoliv z podstromu
- to lze spočítat jedním průchodem, protože to je minimum z low() potomků a in() všech sousedních vrcholů
Algoritmy pro orientované grafy
Detekce cyklů pomocí DFS
Acyklický orientovaný graf (DAG), zdroj, stok
- orientovaný graf bez cyklů
- obsahuje minimálně jeden
- zdroj -- vrchol s degin()=0
- stok -- vrchol s degout()=0
- Dk.:
- jdeme od libovolného vrcholu
- někdy narazíme na stok, jinak by byl graf nekonečný nebo cyklický
- transponujeme a nalezneme zdroj (v GT stok)
Topologické uspořádání DAGu
- částečné uspořádání tvořené hranami DAGu doplněné na lineární
- lineární uspořádání, kde hrany vedou všechny jedním směrem
Konstrukce topologického uspořádání
- out() opakovaného DAGu je v souladu s tímto uspořádáním
Princip indukce podle topologického uspořádání
Počet cest mezi dvěma vrcholy v DAGu
- součet počtů cest do všech předchůdců druhého vrcholu, TI.
Silná souvislost, její komponenty, graf komponent
- mezi vrcholy silně souvislé komponenty existuje cesta v obou směrech
- všechny vrcholy na cyklu jsou součástí stejné komponenty
- tvoří graf komponent, který je DAG
- kdyby byl v grafu komponent cyklus, cyklus je i v podkladovém grafu a všechny komponenty tvoří jednu
Rozklad grafu na komponenty silné souvislosti
- DFS ze stokové komponenty projde pouze tuto komponentu
- jak najít stokovou komponentu?
- pokud vede hrana z komponenty C1 do komponenty C2, bude maximální out() v C1 větší než v C2 -- máme zdrojovou
- zdrojová v GT je stoková v G
- během procházení GT a zavírání vrcholů stavíme zásobník
- odebíráním vrcholů ze zásobníku vždy nejdříve najdeme vrchol stokové komponenty, který můžeme odlomit
Nejkratší cesty
Vzdálenost v grafu
- ohodnocené hrany
- ≥0, jinak je to hodně divočina
- když neexistují záporné cykly, není to tak špatný
- může existovat sled stejně dlouhý jako nejkratší cesta (smyčka na něm je nulová)
- trojúhélníková nerovnost platí
Trojúhelníková nerovnost pro vzdálenost
- platí, ale může tam být sled
Dijkstrův algoritmus
- nastavujeme si budíky, skáčeme na nejbližší zvonící budík
- procházíme body sousední od toho aktuálního, přenastavujeme budíky, pokud mají být menší
Implementace Dijkstrova algoritmu pomocí haldy
- bereme si vrchol pomocí ExtractMin, aktualzujeme budíky pomocí Update
Struktura |
ExtractMin |
Decrease |
Insert |
Výsledná složitost |
pole |
O(n) |
O(1) |
O(1) |
O(n2) |
seřazený linkáč |
O(1) |
O(n) |
O(n) |
O(n2+mn) |
halda |
O(logn) |
O(logn) |
O(logn) |
O((n+m)logn) |
- složitost: O(n⋅TE+m⋅TD+n⋅TI)
- d-regulární haldy better
Obecný relaxační algoritmus
- otevřeme první vrchol
- procházíme otevřené vrcholy a všem sousedům snižujeme h(w) na h(v)+l(v,w)
- tím je otevřeme
- samotný vrchol tím zavřeme
- dijkstra vybírá z otevřených vždy ten s nejmenším h()
Bellmanův-Fordův algoritmus
- relaxace, ale otevřené jsou fronta
Minimální kostry
Jarníkův algoritmus
- začínáme v libovolném bodě
- do kostry přidáváme nejmenší nalezenou hranu
Lemma o řezech
- nejmenší hrana v každém řezu leží na kostře
- na minimální kostře musí existovat cesta mezi vrcholy a a b na koncích minimální hrany
- tato cesta musí vést někudy přes řez
- pokud vede jinou hranou řezu, můžeme hranu odstranit a přidat ab, čímž kostru zmenšíme
- vyžaduje různé hrany, uspořádání se dá dodělat např. čísly hran
Jednoznačnost minimální kostry
(Jarník + Dijkstra)
- udržujeme haldu nalezených hran, ale pouze nejmenší pro každý vrchol -- aktivní hrany
Borůvkův algoritmus
- Jarník od každého bodu
- po každé fázi má každý strom alespoň 2k vrcholů ⇒ fází je logn
- fáze trvá O(m)
Kruskalův algoritmus
- seřadím hrany dle velikosti
- přidávám nejmenší, pokud nevytvoří cyklus
- m·Find, n·Union
- s logaritmickým UnionFindem O(mlogn)
Union-Find
- datová struktura která umí
- Union -- spojit dva vrcholy do jedné množiny
- Find -- zjistit, jsou-li dva stromy v jedné množině
- pamatování si čísel komponent -- Find v O(1), ale Union v O(n)
- pomocí keříků
- Find v O(hloubka kerˇıˊku˚)
- Union v O(1) -- spojíme keříky dohromady (nejdřív musíme Findnout kořen tho)
- pokud vždy lepíme menší keřík pod kořen většího, udržujeme log. hloubku
Vyhledávací stromy
Rozhraní slovníku, množiny a jejich uspořádaných verzí
- slovník: klíč → hodnota
- množina: klíč → nachází se nebo ne
- Find, Insert, Delete, Build, (Min, Max, Next, Prev)
Binární vyhledávací strom (BVS)
- binární vyhledávací strom, kde platí, že všechny prvky levého podstromu jsou menší než kořen a pravého větší
Operace Find, Insert a Delete v BVS
Dokonale vyvážený strom
- počet prvků v levém podstromu je stejný (o jedna rozdílný) než v pravém
- logaritmická hloubka
- když jdeme dolů, pokaždé máme pod sebou polovinu vrcholů než předtím
AVL strom
- hloubka levého podstromu je max. o jedna rozdílná než pravého
Odhad hloubky AVL stromu
- minimální velikost stromu dané hloubky Ah=Ah−1+Ah−2+1
- stačí odhad Ah≥22h
- indukce Ah>22h−1+22h−2=2h⋅(2−21+2−1);(2−21+2−1)>1
Rotace hrany stromu
- převedení levé hrany na pravou a naopak

Operace Insert a Delete v AVL stromech
- jako u BVS, ale rotujeme, když je třeba
- udržujeme ve vrcholu znaménko
- Insert: 5 možností příchodu signálu o zvýšení z levého podstromu, pravý analogicky
- máme + → 0
- máme 0 → --
- máme –
- příchozí vrchol --
- příchozí vrchol +
- příchozí vrchol 0 nenastane
- Delete: všech 6 možností signálu o snížení
(a,b)-stromy
Vícecestný vyhledávací strom a (a,b)-strom
- vyhledávací strom s více klíči v jednom vrcholu
- a≥2,b≥2a−1
- počet synů každého vrcholu je mezi a a b (kořen mezi 2 a b)
- všechny externí vrcholy jsou na poslední hladině
Odhad hloubky (a,b)-stromu
- minimální velikost stromu pro hloubku h je 2ah−1∈Ω(ah)
- hloubka je O(logn)
Operace Insert a Delete v (a,b)-stromech
- Insert
- vložíme list
- ten nesmíme vložit, takže vysuneme o patro výše
- pokud překročíme počet klíčů, prostřední klíč vysuneme opět nahoru
- nikdy nevzniknou moc malé vrcholy protože b≥2a−1,a≤2b−1
- Delete
- v neposlední hladině prohodíme s maximem pravého podstromu
- v poslední hladině
- pokud má (BÚNO pravý) soused minimální počet klíčů, sloučíme se
- jinak minimum (BÚNO pravého) souseda do klíče, klíč jako moje nové maximum, nejlevější souseda nyní nejpravější náš
Volba parametrů (a,b)-stromu
- vysoké hodnoty cool na točivý disky
Písmenkové stromy (trie)
Definice trie
- hrany tvoří písmenka abecedy, pokud slovo končí ve vrcholu, má tam svoji hodnotu
Operace Find, Insert a Delete v trii
- Find -- triv
- Insert -- vyrábíme děti dokud to jde
- Delete -- mažeme děti dokud to jde
- můžeme nasvačit BVS do vrcholů, když máme lorg abecedu
Použití trie k reprezentaci čísel
- RadixSort wahooo
- ne až tak useful ale implementačně hodně ez
Hešování
Hešování s řetězci v přihrádkach
- hešovací funkce umístí prvky do přihrádek
- více prvků v přihrádce reprezentujeme linkáčem
Operace Find, Insert a Delete v hešování s řetězci
- Find -- heš, projití linkáče
- Insert -- heš, projití linkáče, přilepení na konec
- Delete -- heš, projití linkáče, odstranění prvku
Dynamické rozšiřování tabulky
- jako dynamická alokace pole -- vždy dvojnásobíme
c-univerzální systém funkcí
- pravděpodobnost kolize =mc, kde m je počet přihrádek
- celkový počet kolizí nmc
- pokud je n∈O(m), bude kolizí konstantně mnoho
Konstrukce 1-univerzálního systému pomocí skalárního součinu
- prvočíslo p=m, vektorový prostor Zpd, kde d je zvoleno, aby se do vektoru dalo zakódovat jakékoliv vstupní číslo
- náhodně zvolíme vektor t∈Zpd
- spočteme standartní skalární součin ht(x)=⟨t∣x⟩modp
- pokud se vektory liší v jedné složce xi, pak ke kolizi dojde v právě jedné možné hodnotě v ti -- pravděpodobnost p1
Průměrná složitost operací při náhodné volbě hešovací funkce z c-univerzálního systému
O(c)
Rozděl a panuj
Třídění sléváním (Mergesort)
- rozdělíme posloupnost na n přihrádek, potom v každé patře dvě skupinky spojíme dohromady vybíráním minima z první nebo druhé skupinky
- O(nlogn)
- rekurence, do které hooodně dosazujeme
Násobení n-ciferných čísel v čase O(nlog23)
- rozdělíme činitele i,j na poloviny:
i=2m⋅a+b
j=2m⋅c+d
- výsledek se pak dá zapsat jako:
ij=22mac+2mad+2mbc+bd
- vytvoříme tři součiny
S1=(a+b)(c+d)=ac+ad+bc+bd
S2=ac
S3=bd
- ij=22mS2+2m(S1−S2−S3)+S3
Kuchařková věta (Master theorem)
- t(n)=O(nc)+a⋅t(bn)
- t(1)=1
- t(n)=nc+a⋅bcnc+a2⋅b2cnc=nc⋅((bca)0+(bca)1+(bca)2...(bca)logbn)=nc⋅∑i=0logbn(bca)i
- geometrická řada s q=bca, s logbn prvků
- q=1:nclogbn
- q<1: geom. řada konverguje k prvnímu členu (1): nc
- q>1: geom. řada konverguje k poslednímu členu ((bca)logbn):
nc⋅(bca)logbn=bc⋅logbnnc⋅alogbn=ncnc⋅alogbn=alogbn=blogba⋅logbn=nlogba
Strassenův algoritmus na násobení matic (vzorce nezkouším)
- vytvoříme sedm součinů, z nich matici poskládáme
Třídění a vyhledávání
Quickselect – hledání k-tého nejmenšího prvku
- náhodně zvolíme pivot
- rozdělíme prvky na menší a větší
- pokud je před pivotem více či méně prvků než k, zavoláme se na tu skupinu
- pokud ne, máme k-tý prvek
- t(n)=n1⋅1t(n/2);q=21;t(n)∈O(n)
- pokud vždy zahodíme Ω(n) prvků, bude algoritmus v O(n)
Průměrná časová složitost Quickselectu při náhodné volbě pivota
- džbán: skoromedián trefím s pravděpodobností 21, v průměru na to budu potřebovat dva pokusy
- pokaždé, když trefím skoromedián, ukončím epochu
- O(n) epoch, epochy jsou konstantně dlouhé díky džbánu
k-tý nejmenší prvek v lineárním čase (algoritmus s pěticemi)
Quicksort
Průměrná časová složitost Quicksortu při náhodné volbě pivota
- q je v každé epoše kroku ≤1
- epochy konstantně krátké -- se džbánem chodíme pro skoromedián
Dynamické programování
Nejdelší rostoucí podposloupnost
Editační vzdálenost řetězců
Konstrukce optimálního BVS
Floydův-Warshallův algoritmus na výpočet vzdáleností v grafu
- uuuuuh matice something something?
Princip dynamického programování
Grafová interpretace dynamického programování
- DAG stavů
- pokud je DAG polynomiálně velký, vyhráli jsme