Skip list dokumentace

Podobné dokumenty
Amortizovaná složitost. Prioritní fronty, haldy (binární, d- regulární, binomiální, Fibonacciho), operace nad nimi a jejich složitost

Datové struktury 2: Rozptylovací tabulky

AVL stromy. pro každý uzel u stromu platí, že rozdíl mezi výškou jeho levého a pravého podstromu je nejvýše 1 stromy jsou samovyvažující

Stromy, haldy, prioritní fronty

Binární vyhledávací stromy pokročilé partie

IB111 Úvod do programování skrze Python

Vyvažování a rotace v BVS, všude se předpokládá AVL strom

Složitosti základních operací B + stromu

ABSTRAKTNÍ DATOVÉ TYPY

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 21.

Základní datové struktury III: Stromy, haldy

bfs, dfs, fronta, zásobník, prioritní fronta, halda

Stromy. Jan Hnilica Počítačové modelování 14

2 Datové struktury. Pole Seznam Zásobník Fronty FIFO Haldy a prioritní fronty Stromy Hash tabulky Slovníky

Datový typ prioritní fronta Semestrální práce z předmětu 36PT

Datové struktury Úvod

Cílem kapitoly je seznámit studenta se seznamem a stromem. Jejich konstrukci, užití a základní vlastnosti.

bfs, dfs, fronta, zásobník, prioritní fronta, halda

Algoritmizace prostorových úloh

Základní datové struktury

1. Převeďte dané číslo do dvojkové, osmičkové a šestnáctkové soustavy: a) b)

Adresní vyhledávání (přímý přístup, zřetězené a otevřené rozptylování, rozptylovací funkce)

Intervalové stromy. Představme si, že máme posloupnost celých čísel p 0, p 1,... p N 1, se kterou budeme. 1. Změna jednoho čísla v posloupnosti.

Algoritmy I, složitost

Algoritmy a datové struktury

COMPLEXITY

Binární vyhledávací strom pomocí směrníků Miroslav Hostaša L06620

Hledání v textu algoritmem Boyer Moore

Reprezentace aritmetického výrazu - binární strom reprezentující aritmetický výraz

Obecná informatika. Matematicko-fyzikální fakulta Univerzity Karlovy v Praze. Podzim 2012

Prohledávání do šířky = algoritmus vlny

Dynamické datové struktury III.

součet cvičení celkem. známka. Úloha č.: max. bodů: skut. bodů:

přirozený algoritmus seřadí prvky 1,3,2,8,9,7 a prvky 4,5,6 nechává Metody řazení se dělí:

Programování 3. hodina. RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015

Výhody a nevýhody jednotlivých reprezentací jsou shrnuty na konci kapitoly.

Jazyk C++ II. STL knihovna kontejnery část 2

Definice. B-stromu. B-strom řádu m je strom, kde každý uzel má maximálně m následníků a ve kterém platí:

Da D to t v o é v ty t py IB111: Datové typy

Zdůvodněte, proč funkce n lg(n) roste alespoň stejně rychle nebo rychleji než než funkce lg(n!). Symbolem lg značíme logaritmus o základu 2.

Algoritmizace. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010

Algoritmizace prostorových úloh

Dynamicky vázané metody. Pozdní vazba, virtuální metody

Red Black strom (Red Black Tree) Úvod do programování. Rotace. Red Black strom. Rotace. Rotace

B3B33ALP - Algoritmy a programování - Zkouška z předmětu B3B33ALP. Marek Boháč bohacm11

Prioritní fronta, halda

Algoritmizace prostorových úloh

B3B33ALP - Algoritmy a programování - Zkouška z předmětu B3B33ALP. Marek Boháč bohacm11

6. Problém typové anonymity prvků v kolekci Sjednocení typově rozdílných prvků pomocí rozhraní Kolekce pro jeden typ prvků...

bin arn ı vyhled av an ı a bst Karel Hor ak, Petr Ryˇsav y 23. bˇrezna 2016 Katedra poˇ c ıtaˇ c u, FEL, ˇ CVUT

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 12.

Algoritmizace Hashing II. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010

Lineární datové struktury

Náplň. v Jednoduché příklady na práci s poli v C - Vlastnosti třídění - Způsoby (algoritmy) třídění

Lineární spojový seznam (úvod do dynamických datových struktur)

8. Geometrie vrací úder (sepsal Pavel Klavík)

Programování v C++, 2. cvičení

Dijkstrův algoritmus

IB111 Úvod do programování skrze Python

Složitost algoritmů. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava

V každém kroku se a + b zmenší o min(a, b), tedy vždy alespoň o 1. Jestliže jsme na začátku dostali 2

Druhá skupina zadání projektů do předmětu Algoritmy II, letní semestr 2014/2015

Čtvrtek 3. listopadu. Makra v Excelu. Obecná definice makra: Spouštění makra: Druhy maker, způsoby tvorby a jejich ukládání

Content Aware Image Resizing

Časová a prostorová složitost algoritmů

Michal Krátký. Úvod do programování. Cíl kurzu. Podmínky získání zápočtu III/III

Algoritmizace Dynamické programování. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010

zejména Dijkstrův algoritmus pro hledání minimální cesty a hladový algoritmus pro hledání minimální kostry.

Fronta (Queue) Úvod do programování. Fronta implementace. Fronta implementace pomocí pole 1/4. Fronta implementace pomocí pole 3/4

TGH07 - Chytré stromové datové struktury

5 Rekurze a zásobník. Rekurzivní volání metody

Programování v C++ 1, 16. cvičení

Zdokonalování gramotnosti v oblasti ICT. Kurz MS Excel kurz 6. Inovace a modernizace studijních oborů FSpS (IMPACT) CZ.1.07/2.2.00/28.

Semestrální práce 2 znakový strom

Ukážeme si lineární algoritmus, který pro pevné k rozhodne, zda vstupní. stromový rozklad. Poznamenejme, že je-li k součástí vstupu, pak rozhodnout

autoři: Rudolf Bayer, Ed McCreight všechny vnější uzly (listy) mají stejnou hloubku ADS (abstraktní datové struktury)

VzorTest-1. Prohlídka náhledu

Šablony, kontejnery a iterátory

Algoritmus pro hledání nejkratší cesty orientovaným grafem

TGH07 - Chytré stromové datové struktury

Cvičení ze statistiky - 5. Filip Děchtěrenko

Testování prvočíselnosti

TÉMATICKÝ OKRUH Softwarové inženýrství

13. Třídící algoritmy a násobení matic

1. Dědičnost a polymorfismus

Abstraktní datové typy FRONTA

Nechť je číselná posloupnost. Pro všechna položme. Posloupnost nazýváme posloupnost částečných součtů řady.

ADT prioritní fronta. Haldy. Další operace nad haldou. Binární halda. Binomické stromy. Časová složitost jednotlivých operací.

Vzdálenost jednoznačnosti a absolutně

cv3.tex. Vzorec pro úplnou pravděpodobnost

NPRG030 Programování I, 2018/19 1 / :03:07

Grafové algoritmy. Programovací techniky

Výroková a predikátová logika - III

Úvod do informatiky. Miroslav Kolařík. Zpracováno dle učebního textu R. Bělohlávka: Úvod do informatiky, KMI UPOL, Olomouc 2008.

Hledáme efektivní řešení úloh na grafu

Grafové algoritmy. Programovací techniky

Select sort: krok 1: krok 2: krok 3: atd. celkem porovnání. výběr nejmenšího klíče z n prvků vyžaduje 1 porovnání

Aplikace. vliv na to, jakou mají strukturu i na to, jak pracné je je vyvinout. Bylo vypozorováno, že aplikace je možné rozdělit do skupin

Pokročilé haldy. prof. Ing. Pavel Tvrdík CSc. Fakulta informačních technologií České vysoké učení technické v Praze c Pavel Tvrdík, 2010

Dynamické datové struktury IV.

Transkript:

Skip list dokumentace Václav Brodec Úvod Skip list je pravděpodobnostní datová struktura dosahující s vysokou pravděpodobností logaritmické složitosti pro běžné operace (přidání prvku, odebrání, nalezení podle klíče). Indexovaný skip list je rozšířením skip listu, který dovoluje i přístup k prvkům struktury pomocí indexů v logaritmickém čas. Předmětem zápočtové práce je implementace této struktury. Rozhraní Knihovna SkipList je tvořena třemi hlavními třídami. Jejím základem je abstraktní třída AbstractSkipList, která je rozšířena ve svých dvou potomcích SkipList a SkipListSet. Tyto dvě třídy se liší tím, že dovolují resp. vylučují existenci prvků se stejným hodnotami. Třída AbstractSkipList je naplněním standardního rozhraní Javy Collection, které až na výjimky plynoucí z povahy vlastní datové struktury zcela naplňuje. Navíc přidává některé metody typické pro standardní rozhraní List, které jsou uplatnitelné pro indexovaný skip list. Odvození od rozhraní standardní knihovny bylo kromě jiných výhod zvoleno především proto, že při vývoji poskytovalo rozumný funkční rozsah, který je vhodné při naprogramování jakékoli datové struktury splnit. Datová struktura je realizována jako generická třída, jejíž prvky mohou být datového typu s definovaným uspořádáním, popř. může být při konstrukci objektu uspořádání definováno externě pomocí Comparatoru. Z algoritmického hlediska zajímavé operace jsou: Member (realizováno contains(objekt)) testuje přítomnost odpovídajícího prvku v kolekci. Insert (realizováno metodou add(prvek)) zajistí přítomnost prvku v kolekci. Delete (realizováno metodou remove(objekt)) zajistí odstranění odpovídajícího prvku z kolekce. InsertToIndex (realizováno metodou add(index, prvek)) vloží prvek do kolekce do umístění na danou pozici (index), pokud tím nebude porušeno uspořádání prvků. GetFromIndex (realizováno metodou get(index)) vrátí prvek z daného indexu.

IndexOf (realizováno metodou indexof(objekt)) vrátí index odpovídajícího prvku. DeleteFromIndex (realizováno metodou remove(index)) odstraní prvek daného indexu. SetIndex (realizováno metodou set(index, element)) nahradí prvek daného indexu jiným, pokud tím nebude narušeno uspořádání. Popis datové struktury Základem skip listu je spojový seznam, který obsahuje všechny prvky uspořádané podle klíče. Předpokládáme, že tento seznam je implementován se dvěma zvláštními uzly hlavou a ocasem, které jsou umístěny na jeho koncích a jejich klíčovou hodnotou je -, resp. +. Tento seznam je dále rozšířen o další vrstvy, spojové seznamy s hlavou a ocasem. Ty si lze představit tak, že se nachází nad základní vrstvou. V dalších vrstvách se nacházejí opět uspořádané některé vybrané prvky ze základní vrstvy. Platí při tom, že pokud se prvek nachází v nějaké vrstvě, nachází se nutně i ve všech vrstvách nižších. Další vrstvy tedy tvoří nad základním spojovým seznamem jakési zkratky, které spojují vybrané prvky. Čím výše, tím jsou tyto spojnice delší. Vyhledávání ve struktuře Nejdůležitější operací nad skip listem je Search. Chceme li nalézt prvek s daným klíčem, postupujeme tak, že začneme v nejvyšším patře struktury u hlavy, na níž nastavíme pomyslný ukazatel. Z výchozí pozice přečteme klíč na dalším prvku směrem vpravo po spoji. Pokud je jeho klíč menší, můžeme se na něj přesunout a podívat se opět na jeho pravého souseda. Pokud budeme mít štěstí, tak těmito kroky překonáme značné množství prvků, které se v základní vrstvě nachází před očekávanou pozici prvku s hledaným klíčem. Pokud se stane, že následný prvek má již klíč větší, než je klíč hledaný, sestoupíme po vertikále o patro níže a pokračujeme dále. Je jasné, že tímto postupem buďto nalezneme prvek s hledaným klíčem, nebo se dostaneme mezi dva prvky v základní vrstvě, jejichž klíčové hodnoty existenci prvku ve struktuře vylučují, nebo se dostaneme ve svrchním patře až na ocas (když velikost hledaného klíče

přesahuje rozsah hodnot ve skip listu), a nebo sejdeme po vertikále až do hlavy základního seznamu (když je hledaný klíč menší než rozsah hodnot klíčů). Konstrukce Před vlastním rozborem složitosti operace Search je nutné osvětlit, jakým způsobem skip list vzniká. Operace Insert má průběh takřka totožný se Search, až na to, že si po cestě pamatuje uzly, ve kterých bylo nutné sejí o patro níže. Po nalezení intervalu, kam patří nový klíč se provede toto: 1. Nově vzniklý uzel s daným klíčem se vloží do základního seznamu. 2. S jistou pevnou, předem zvolenou pravděpodobností p (obvykle 1/2 či 1/3) dojde k propagaci uzlu o patro výše. Tedy s využitím zapamatovaného seznamu uzlů se přidá nový uzel s daným klíčem do spojového seznamu na vyšší hladině, pokud nám na pomyslné minci (řídící se pravděpodobností p pro to, že padne panna) padne panna. 3. S pravděpodobností p 2 dojde k propagaci uzlu do další vyšší hladiny. 4. S pravděpodobností p 3 dojde k propagaci uzlu do další vyšší hladiny. 5. 6. Obdobný krok se provede pro všechny vrstvy až do předem nastavené maximální výšky skip listu. Po vložení nového prvku tedy může aktuální výška skip listu vzrůst díky novým hladinám, na kterých se vyskytují seznamy obsahující zatím pouze hlavu, ocas a právě přidaný prvek. Rozbor časové složitosti operace Search Definice: Parametrizovaný jev E(a) nastává s vysokou pravděpodobností, pokud pro každé a 1 lze nalézt takové konstanty, se kterými jev nastává s pravděpodobností alespoň 1 - c(a)/n a, kde c(a)/n a označujeme jako pravděpodobnost chyby. Tvrzení: Skip list obsahující n prvků má s velkou pravděpodobností O(log n) pater. Důkaz: P(skip list má nejvýše c log(n) pater) 1 P(skip list má více než c log(n) pater) 1 n P(prvek byl při vkládání alespoň c log(n) propagován) 1 n (p c log(n) ) 1 n 1/n c 1 1/n c-1. Uvedená nerovnost vychází z toho, že P(E 1 E 2 E k ) P(E 1 ) + P(E 2 ) P(E k ). Dále víme, že p < 1. Tím je tedy tvrzení dokázáno, neboť pro všechna a můžeme c v odhadu počtu pater zvolit tak, aby byla požadovaná pravděpodobnost alespoň 1 1/n a.

Tvrzení: Provedení operace Search ve skip listu obsahujícím n prvků má s vysokou pravděpodobností složitost O(log n). Důkaz: Počítejme přesuny pomyslného ukazatele po uzlech nutné k nalezení uzlu s hledaným klíčem. Pokud proces hledání krokujeme směrem od konce, tj. od nalezeného uzlu, lze přesuny rozdělit na dva druhy: přesuny doleva (během vlastního Search jsou doprava) uzel ve kterém se před přesunem (po přesunu) nacházíme, nebyl při svém přidání vyzvednut do vyššího patra, přesuny nahoru (během vlastního Search jsou dolu) uzel ve kterém se před přesunem (po přesunu) nacházíme, byl při svém přidání vyzvednut do vyššího patra. Zpětná analýza hledání končí tam, kde Search začíná: v hlavě vrchního seznamu. Jelikož víme, že počet pater skip listu je s vysokou pravděpodobností O(log n), máme počet přesunů nahoru (dolu) s vysokou pravděpodobností shora omezen c log(n). Typ přesunu při analýze nám vždy určuje nezávislý hod pomyslnou mincí. Na to, abychom překonali všechna patra, potřebujeme c log(n) hodů, ve kterých nám padne hlava. Počet všech přesunů tedy lze omezit počtem hodů mincí, které jsou potřeba, aby nám s vysokou pravděpodobností padla c log(n)-krát panna. Zbývá dokázat, že je jich Θ(log n). Tvrzení: Počet hodů mincí řídící se pravděpodobností p pro získání c log(n) výsledků panna je v Θ(log n). Důkaz: Počet hodů je zřejmě v Ω(log n). Dále odhadněme pomocí Bernoulliho schématu: P mc log n, c log n ( ) ( ) ( m 1 c n p ) c log padne nejvýše log - krát panna 1 n kde výraz m c log(n) označuje provedený počet hodů. S využitím nerovnosti x y y e toto lze dále shora omezit: x x

mc log n c log n ( ) ( m 1 ) c log n ( ) ( m 1 1 1 ) c log n c log n ( ) ( 1 ) ( m 1 p e p me p ) log( me) c log n ( ) ( ) ( m 1 ) c log n log n c log ( me) 1 p 1 p ( 1 p) 1 pro a c a n ( log( me) + m 1). mc log n c log n c log n ( + m 1) 1 log n ( c) log( me) ( 1 p) ( + m 1) c log n Tedy pro zadané a z definice vysoké pravděpodobnosti snadno nalezneme konstantu m dostatečně velkou (tj. upravíme počet hodů) tak, aby vztah platil a zároveň se budeme stále nacházet v mezích O(log n). Tím je důkaz hotov. Další operace Operace Delete je podobná Insertu v tom, že si při průchodu opět zapamatováváme uzly, ve kterých jsme sestupovali. Po odstranění nalezeného uzlu pak tyto uzly navážeme na jeho následníky. Jelikož jsou operace Insert a Delete až na aktualizaci ukazatelů podle zapamatovaných seznamů takřka totožné se Search (alias Member) a jelikož již víme, že počet pater (a tedy i počet zapamatovaných uzlů) skip listu je logaritmický vzhledem k počtu vrcholů, je snadné nahlédnout, že i tyto operace mají logaritmickou časovou složitost. V souvislosti s operacemi je nutné připomenout rozdíl mezi variantami SkipList a SkipListSet. Ve variantě SkipList jsou duplicitní klíče v listu umisťovány dle principu LIFO, tj. poslední přidaný duplikát se v základním seznamu nachází nejblíže začátku. Indexovaný skip list Pokud ke každému ukazateli na následníka přiřadíme i jeho délku vyjadřující počet úseků v základním seznamu, přes který přeskakujeme, lze v logaritmickém čas provádět i operace pracující s pořadím prvku v seznamu. Operace GetFromIndex se provádí tak, že začínáme v hlavě vrchního seznamu a poté opět procházíme skip listem obdobně jako u Search. Jediný rozdíl je v tom, že místo porovnávání klíčů nesčítáváme délky úseků a porovnáváme součet s hledaným indexem. V případě, že požadovaný index překročíme, odečteme délku posledního přidaného úseku a sestoupíme o patro níže. Související operace pracující s indexy jsou přímými obdobami pro operace pracující s hodnotami klíčů. Až na IndexOf, která hledá podle hodnoty klíče, přestože si při tom z délek úseků nasčítává index.

Ukázky Václav Brodec Součástí JAR archivu je kromě zdrojových kódů a přeložených tříd knihovny také krátká demonstrace užití (cz.cuni.mff.ms.brodecva.skiplist.demo.main), kterou lze přímo spustit. Kromě příkladů volání základních operací obsahuje i příklad počítající plovoucí medián. Poznámky k implementaci Na rozdíl od popisu algoritmu výše jsou uzly skip listu ukládány pro všechny patra společně. Tedy pro jeden klíč existuje pouze jeden objekt Node, ze kterého vedou odchozí Linky až do patra, ve kterém se uzel nejvýše nachází (Šetří to paměť.). Hlava a ocas neobsahují žádnou minimální resp. maximální hodnotu (Nelze takto implementovat pro variabilní typy prvků.). Pro znázornění aktuální podoby skip listu (uspořádání uzlů) je užitečná metoda print, která jako argument přijímá délku řádku (slouží pro zalomení příliš dlouhých výpisů). Součástí JAR archivu je JavaDoc dokumentace. Možnosti dalšího rozšíření a úprav Knihovna byla vyvíjena jako demonstrační. Proto obsahuje několik míst, které mohou brzdit její výkon. Například: Zbytečně často se volá generátor náhodných čísel. Pro nastavenou pravděpodobnost p 0.5 by bylo vhodné generovat dlouhé číslo a jeho binární zápis pak užít pro rozhodování o propagaci uzlů. V současné podobě má struktura značné nároky na paměť spočívající ve velkém počtu uložených ukazatelů na jeden prvek. Jejich počet by šel redukovat za cenu snížení názornosti. Nastavená pravděpodobnost propagace není zcela optimální. Algoritmy předpokládají nízkou výpočetní náročnost operace porovnání klíčů. Hledání blízkých hodnot by šlo urychlit využitím techniky prstů, které si pamatují hledaná místa. Pro implementaci byla zvolena varianta, která si v uzlech pamatuje pouze dopředné ukazatele. V případě ukazatelů do obou směrů by bylo možné (za cenu zvýšení spotřebované paměti) snadněji implementovat metody modifikující skip list (především pro iterátor, kde to v této verzi není nepodporováno). Mimo to by bylo možné třídy rozšířit o další metody dovolující slévání a štěpení skip listů, práci s daným rozsahem či podlistem.

Zdroje Václav Brodec William Pugh - Skip Lists: A Probabilistic Alternative to Balanced Trees Erik D. Demaine and Charles E. Leiserson - Introduction to Algorithms William Pugh - A Skip List Cookbook