Dynamické dátové štruktúry a algoritmy

Rozšírte si vedomosti o dynamických dátových štruktúrach a algoritmoch. Zistite, ako fungujú spájané zoznamy, stromy, grafy, triedenie a vyhľadávanie. Perfektný prehľad pre študentov informatiky a prípravu na maturitu!

Podcast

Dátové štruktúry: Od chaosu k poriadku0:00 / 12:55
0:001:00 zostáva

Dynamické dátové štruktúry a algoritmy sú základnými piliermi informatiky, ktoré nám umožňujú efektívne organizovať a spracovávať dáta. Ich pochopenie je kľúčové pre každého študenta programovania a prípravu na maturitu či skúšky. Tento článok vám poskytne komplexný prehľad o týchto štruktúrach a algoritmoch, ich vlastnostiach a praktickom využití. Zameriame sa na spájané zoznamy, stromy, grafy, triediace algoritmy a miery zložitosti, ktoré sú esenciálne pre optimalizáciu kódu a efektívne riešenie úloh. Budeme sa venovať aj vyhľadávaniu informácií v tabuľkách a reprezentácii množín, aby ste získali ucelený obraz o dynamickom spracovaní dát.

Základy dynamických dátových štruktúr a algoritmov

Dynamické dátové štruktúry sú také štruktúry, ktorých veľkosť sa môže meniť počas behu programu. To znamená, že prvky môžeme podľa potreby pridávať, odoberať alebo prepájať. Sú obzvlášť užitočné v situáciách, keď dopredu nepoznáme presný počet prvkov, ktoré budeme potrebovať.

Pri výbere správnej dátovej štruktúry a algoritmu je dôležité sledovať efektívnosť operácií. Čas behu algoritmu sa označuje ako T(n), kde 'n' reprezentuje veľkosť vstupu. Kľúčová je asymptotická zložitosť, ktorá opisuje, ako sa mení čas behu pri zväčšovaní vstupu.

Miery zložitosti algoritmov

Pre hodnotenie efektívnosti algoritmov používame rôzne miery zložitosti. Tieto miery nám pomáhajú porovnať algoritmy a vybrať ten najvhodnejší pre danú úlohu.

  • Časová zložitosť: Vyjadruje počet operácií v závislosti od veľkosti vstupu 'n'. Najčastejšie sa používa notácia O (Big O notácia), ktorá udáva horný odhad rastu času.
  • O(1) – konštantná zložitosť, čas behu nezávisí od 'n'.
  • O(log n) – logaritmická zložitosť, typická pre efektívne vyhľadávanie.
  • O(n) – lineárna zložitosť, čas rastie priamo úmerne s 'n'.
  • O(n log n) – efektívna zložitosť pre porovnávacie triediace algoritmy.
  • O(n²) – kvadratická zložitosť, neefektívna pri veľkých dátach.

Rozlišujeme tiež najlepší prípad (best-case), priemerný prípad (average-case) a najhorší prípad (worst-case), ktoré popisujú rôzne scenáre výkonu algoritmu.

  • Pamäťová zložitosť: Udáva množstvo dodatočnej pamäte, ktorú algoritmus potrebuje.
  • In-place algoritmy: O(1) alebo O(log n) – minimálna dodatočná pamäť.
  • Externé algoritmy: O(n) – vyžadujú pamäť úmernú veľkosti vstupu.

Odhady zložitosti

Ako odhadnúť zložitosť algoritmu?

  • Iteratívne algoritmy:
  • Jeden cyklus: O(n)
  • Dva vnorené cykly: O(n²)
  • Rekurzívne algoritmy:
  • Používajú sa rekurentné vzťahy a Master theorem.
  • Typický prípad: rozdelenie na polovice vedie k log n úrovniam, práca na každej úrovni je 'n', výsledok O(n log n).

Spájané zoznamy: flexibilná dátová štruktúra

Spájané zoznamy sú základnými dynamickými dátovými štruktúrami. Na rozdiel od polí nemusia byť prvky uložené súvisle v pamäti, čo im dodáva veľkú flexibilitu pri pridávaní a odoberaní prvkov.

Jednosmerný spájaný zoznam

V jednosmernom spájanom zozname obsahuje každý prvok, nazývaný vrchol, odkaz (referenciu) na nasledujúci prvok. Prístup k celému zoznamu je zabezpečený premennou odkazujúcou na prvý vrchol.

Schéma jednosmerného zoznamu: [ dáta | next ] → [ dáta | next ] → [ dáta | next ] → None

Každý vrchol má dve časti:

  • dáta: Uložená hodnota.
  • next: Odkaz na ďalší vrchol (v Pythone často None pre posledný prvok).

Vlastnosti jednosmerného spájaného zoznamu:

  • Prvky nemusia byť uložené vedľa seba v pamäti.
  • Ľahké pridávanie a odoberanie prvkov.
  • Prístup k prvkom je sekvenčný – musíme prechádzať postupne od začiatku.

Dvojito spájaný zoznam

V dvojito spájanom zozname obsahuje každý vrchol dva odkazy:

  • prev: Odkaz na predchádzajúci prvok.
  • next: Odkaz na nasledujúci prvok.

Schéma dvojito spájaného zoznamu: None ← [prev | dáta | next] ⇄ [prev | dáta | next] ⇄ [prev | dáta | next] → None

Vlastnosti dvojito spájaného zoznamu:

  • Zoznam môžeme prechádzať v oboch smeroch (dopredu aj dozadu).
  • Jednoduchšie vymazávanie a vkladanie prvkov, pretože máme odkazy na obe strany.
  • Vyžaduje viac pamäte, keďže každý vrchol má dva odkazy.

Cyklický spájaný zoznam

V cyklickom spájanom zozname posledný prvok neukazuje na None, ale späť na prvý prvok zoznamu. Tým vzniká uzavretý kruh. Môže byť jednosmerný aj dvojsmerný, pričom sa často zaoberáme len jednosmerným cyklickým zoznamom.

Schéma cyklického zoznamu: [ dáta | next ] → [ dáta | next ] → [ dáta | next ] ↑_____________________________________|

Vlastnosti cyklického spájaného zoznamu:

  • Zoznam nemá „koniec“ – po poslednom prvku nasleduje opäť prvý.
  • Zoznam sa dá prechádzať dookola stále dokola.
  • Často sa používa pri plánovaní procesov (napríklad Round-robin, simuláciách alebo hrách).

Základné operácie so spájaným zoznamom zahŕňajú vytvorenie prázdneho zoznamu, pridanie prvku, odstránenie prvku, vyhľadanie prvku a prechod zoznamom. Tieto operácie sa v programovacích jazykoch ako Python zvyčajne implementujú ako vlastné metódy triedy.

Stromové dátové štruktúry: hierarchické usporiadanie dát

Strom je hierarchická dátová štruktúra, ktorá je špeciálnym typom grafu. Ide o súvislý acyklický graf, čo znamená, že medzi jeho vrcholmi neexistujú žiadne cykly a medzi ľubovoľnými dvoma vrcholmi existuje cesta.

Strom sa skladá z vrcholov (uzlov) a hrán (spojení medzi vrcholmi). Každý strom má jeden špeciálny vrchol nazývaný koreň (root), z ktorého celá štruktúra začína.

Základné pojmy v stromoch

  • Koreň (root): Najvyšší vrchol stromu, začiatok štruktúry.
  • Rodič (parent): Vrchol, ktorý má pod sebou ďalšie vrcholy.
  • Potomok (child): Vrchol, ktorý je priamo pod rodičom.
  • Podstrom: Strom, ktorý vznikne zvolením jedného vrcholu a všetkých jeho potomkov.
  • Hĺbka vrcholu: Počet hrán od koreňa k danému vrcholu.
  • Výška stromu: Najväčšia hĺbka vrcholu v strome.

Binárny strom

Binárny strom je najčastejšie používaný typ stromu. V binárnom strome môže mať každý vrchol najviac dvoch potomkov: ľavého potomka a pravého potomka.

Príklad schémy:

 A
 / \
 B C
/ \ / \
D E

Prechádzanie stromu (Tree Traversal)

Pri práci so stromami je dôležité vedieť ich prechádzať. Najznámejšie metódy sú:

  • Preorder (pre-order):
  1. Koreň
  2. Ľavý podstrom
  3. Pravý podstrom
  • Inorder (in-order):
  1. Ľavý podstrom
  2. Koreň
  3. Pravý podstrom
  • Postorder (post-order):
  1. Ľavý podstrom
  2. Pravý podstrom
  3. Koreň

Binárny vyhľadávací strom (BST)

Množiny sa často implementujú pomocou binárnych vyhľadávacích stromov (BST). V BST platí špecifické pravidlo usporiadania dát:

  • Všetky prvky v ľavom podstrome sú menšie ako koreň.
  • Všetky prvky v pravom podstrome sú väčšie ako koreň.

Príklad BST:

 10
 / \
 5 15
 / \
2 7

Nevyvážený strom

Ak sú prvky vkladané v zoradenom poradí (napríklad 1, 2, 3, 4, 5), strom môže degenerovať do lineárnej štruktúry, ktorá sa správa ako spájaný zoznam. Takýto nevyvážený strom má nevýhody, pretože operácie na ňom môžu mať časovú zložitosť O(n), čo je neefektívne.

Vyvážený strom

Vyvážené stromy slúžia na reprezentáciu usporiadanej množiny prvkov s cieľom zefektívniť prácu. Prvky môžu byť zložitejšieho typu a sú usporiadané podľa nejakého kľúča (napr. čísla).

Príklad vyváženého stromu:

 4
 / \
 2 6
 / \ / \
 1 3 5 7

Výhody vyvážených stromov:

  • Operácie sú efektívne, pretože výška stromu je logaritmická.
  • Časová zložitosť je približne O(log n).

Príkladom vyváženého stromu je AVL strom.

Základné operácie s BST

  • INSERT(x) – vloženie prvku: Nový prvok vkladáme na miesto, aby zostala zachovaná vlastnosť binárneho vyhľadávacieho stromu.
  • DELETE(x) – odstránenie prvku: Pri odstraňovaní môžu nastať tri prípady:
  1. Odstraňovaný vrchol je list: Jednoducho ho odstránime.
  2. Odstraňovaný vrchol má jedného potomka: Nahradíme ho jeho potomkom.
  3. Odstraňovaný vrchol má dvoch potomkov: Nahradíme ho napríklad najmenším prvkom z pravého podstromu alebo najväčším prvkom z ľavého podstromu.

Použitie stromov

Stromy sú mimoriadne všestranné a používajú sa v mnohých oblastiach:

  • Organizovanie dát v databázach.
  • Vyhľadávacie algoritmy (napr. v súborových systémoch).
  • Reprezentácia súborových systémov.
  • Implementácia výrazov v programovaní.
  • Huffmanov kód: Efektívne kódovanie znakov na zníženie veľkosti uložených dát. Častejšie znaky dostávajú kratší kód. Vytvára sa pomocou Huffmanovho stromu, kde ľavá hrana = 0 a pravá hrana = 1. Kód znaku vznikne zapísaním 0 a 1 na ceste od koreňa k listu.

Grafy: modelovanie vzťahov medzi objektmi

Graf je dátová štruktúra, ktorá slúži na reprezentáciu vzťahov medzi dvojicami objektov. Matematicky je graf definovaný ako dvojica G=(V,E), kde V je množina vrcholov (vertices) a E je množina hrán (edges), ktoré spájajú vrcholy.

Vrchol predstavuje objekt a hrana vzťah medzi dvoma vrcholmi (napríklad mestá ako vrcholy a cesty medzi nimi ako hrany).

Typy grafov

  • Neorientovaný graf:
  • Hrany nemajú smer. Hrana medzi A a B znamená, že spojenie existuje v oboch smeroch (A—B).
  • Používa sa napríklad pri cestných sieťach alebo mapách.
  • Orientovaný graf (digraf):
  • Hrany majú smer. Hrana sa zapisuje ako usporiadaná dvojica vrcholov (A → B). To znamená spojenie z A do B, ale nemusí existovať z B do A.
  • Používa sa napríklad pri závislostiach úloh, sociálnych sieťach alebo smerovaných sieťach.

Reprezentácia grafu

Graf je možné reprezentovať rôznymi spôsobmi:

  • Zoznam susedov:
  • Každý vrchol obsahuje zoznam vrcholov, s ktorými je spojený (napr. A → B, C).
  • Výhody: Menšia pamäťová náročnosť.
  • Nevýhody: Pomalšie zisťovanie existencie konkrétnej hrany.

Prehľadávanie grafu

Na prehľadávanie grafov sa často používajú dva kľúčové algoritmy:

  • DFS – Depth First Search (prehľadávanie do hĺbky):
  • Najprv spracuje vrchol a potom rekurzívne pokračuje v prehľadávaní všetkých svojich susedov do hĺbky.
  • BFS – Breadth First Search (prehľadávanie do šírky):
  • Algoritmus najprv prejde všetky vrcholy vzdialené o 1 od aktuálneho, potom všetky vzdialené o 2 atď.

Použitie grafov

Grafy majú široké uplatnenie v praxi:

  • Modelovanie dopravných sietí.
  • Sociálne siete.
  • Počítačové siete.
  • Plánovanie úloh.
  • Vyhľadávanie najkratšej cesty (napr. v GPS navigácii).

Triediace algoritmy: usporiadanie dát

Triediace algoritmy slúžia na usporiadanie prvkov podľa určitého kľúča (napríklad vzostupne). Pri ich hodnotení sa sleduje časová a pamäťová zložitosť, stabilita a praktická použiteľnosť.

Merge Sort (triedenie zlučovaním)

Merge Sort patrí medzi algoritmy typu divide and conquer (rozdeľ a panuj):

  1. Rozdelí pole na dve polovice.
  2. Rekurzívne ich utriedi.
  3. Spojí (merge) zoradené časti.
  • Rekurentný vzťah: T(n) = 2T(n/2) + O(n). Riešením je T(n) = O(n log n).
  • Zložitosť: best-case: O(n log n), average-case: O(n log n), worst-case: O(n log n).
  • Vlastnosti:
  • Stabilný algoritmus (zachováva relatívne poradie rovnakých prvkov).
  • Vyžaduje dodatočnú pamäť O(n).
  • Vhodný pre veľké dáta a externé triedenie.

Quick Sort (rýchle triedenie)

Quick Sort je tiež algoritmus typu divide and conquer:

  1. Vyberie sa pivot (rozdielový prvok).
  2. Rozdelí prvky na menšie a väčšie ako pivot.
  3. Rekurzívne sa triedia vzniknuté časti.
  • Priemerný prípad: T(n) = 2T(n/2) + O(n), čo vedie k O(n log n).
  • Najhorší prípad: T(n) = T(n-1) + O(n), čo vedie k O(n²).
  • Zložitosť: best-case: O(n log n), average-case: O(n log n), worst-case: O(n²).
  • Vlastnosti:
  • Nestabilný algoritmus.
  • Pamäť: O(log n) (vďaka rekurzii).
  • Veľmi rýchly v praxi (dobrá cache lokalita).

Porovnanie triediacich algoritmov

VlastnosťMerge SortQuick Sort
Čas (priemerný)O(n log n)O(n log n)
Čas (najhorší)O(n log n)O(n²)
PamäťO(n)O(log n)
StabilitaÁnoNie
Praktické použitieExterné triedenieInterné triedenie

Dolná hranica triedenia

Pre porovnávacie triedenie platí dolná hranica Ω(n log n). To znamená, že žiadny porovnávací algoritmus nemôže byť asymptoticky rýchlejší ako O(n log n).

Kartičky

1 / 45

Čo je graf a ako je formálne definovaný v matematike?

Graf je dátová štruktúra na reprezentáciu vzťahov medzi dvojicami objektov, formálne G=(V,E), kde V je množina vrcholov a E je množina hrán spájajúcic

Ťukni na otočenie · Potiahni na navigáciu

Vyhľadávanie informácií v tabuľkách

Efektívne vyhľadávanie je kľúčové pre prácu s dátami. Existujú rôzne techniky v závislosti od usporiadania dát.

Sekvenčné (lineárne) vyhľadávanie

Sekvenčné vyhľadávanie je najjednoduchší spôsob.

  • Postup: Začneme od prvého prvku a postupne porovnávame každý prvok s hľadanou hodnotou, až kým sa hodnota nenájde alebo neprejdeme celú tabuľku.
  • Výhody: Jednoduchá implementácia, funguje aj na neusporiadaných dátach.
  • Nevýhody: Pomalé pri veľkých množstvách dát.
  • Časová zložitosť: best-case: O(1), average-case: O(n), worst-case: O(n).

Binárne vyhľadávanie

Binárne vyhľadávanie je efektívnejší algoritmus, ktorý sa používa iba na usporiadaných dátach.

  • Postup: Nájdeme stred tabuľky, porovnáme hľadaný prvok so stredovým. Ak je menší, pokračujeme v ľavej polovici, ak je väčší, v pravej. Postup opakujeme, kým prvok nenájdeme alebo tabuľka nebude prázdna.
  • Výhody: Veľmi rýchle vyhľadávanie.
  • Nevýhody: Tabuľka musí byť usporiadaná.
  • Časová zložitosť: best-case: O(1), average-case: O(log n), worst-case: O(log n).

Hašovanie

Hašovanie je technika, pri ktorej sa prvok pomocou hašovacej funkcie priamo mapuje na pozíciu v tabuľke (hašovacia tabuľka).

  • Postup:
  1. Na kľúč aplikujeme hašovaciu funkciu.
  2. Funkcia vypočíta index v tabuľke.
  3. Na tomto mieste uložíme alebo vyhľadáme prvok.
  • Výhoda: Veľmi rýchle operácie (takmer konštantný čas).
  • Nevýhoda: Môžu vzniknúť kolízie.

Hašovacia funkcia

Hašovacia funkcia transformuje kľúč na index tabuľky (napr. h(k) = k mod m, kde 'k' je kľúč a 'm' je veľkosť tabuľky).

Dobrá hašovacia funkcia by mala:

  • Rovnomerne rozdeľovať prvky.
  • Minimalizovať kolízie.
  • Byť rýchla na výpočet.

Kolízie

Kolízia nastáva, keď dva rôzne kľúče majú rovnaký index v tabuľke. Jedným z hlavných spôsobov riešenia kolízií je hašovanie reťazením. Pri tejto metóde má každá pozícia tabuľky zoznam prvkov. Ak nastane kolízia, nový prvok sa pridá do zoznamu na danom indexe.

Reprezentácia množín: jedinečné usporiadanie prvkov

Množina je abstraktný dátový typ (ADT), ktorý obsahuje neusporiadané prvky bez opakovania. V informatike sa množiny používajú pri práci s databázami, grafmi alebo pri vyhľadávaní údajov.

Základné operácie nad množinou sú: vloženie prvku, odstránenie prvku, zistenie príslušnosti prvku, zjednotenie množín, prienik množín a rozdiel množín.

Množinu možno implementovať rôznymi dátovými štruktúrami:

Bitový vektor

Bitový vektor je pole bitov, kde každý bit reprezentuje jeden prvok z univerzálnej množiny. Hodnota 1 znamená, že prvok je v množine, hodnota 0, že prvok v množine nie je.

Príklad: Univerzálna množina {0,1,2,3,4}. Bitový vektor [1,0,1,0,1] reprezentuje množinu {0,2,4}.

Reprezentácia množiny pomocou poľa

Množinu možno uložiť aj ako pole prvkov, napríklad [5, 8, 12, 20].

  • Operácie:
  • Vloženie prvku: pridanie do poľa.
  • Vyhľadanie prvku: lineárne prehľadanie poľa.
  • Odstránenie prvku: nájdenie prvku a jeho vymazanie.
  • Časová zložitosť:
  • Vyhľadanie: O(n)
  • Vloženie prvku: O(1) (na koniec, ak nie je treba zachovať poradie a duplicity sú povolené), ale ak treba overiť duplicitu, potom O(n).
  • Odstránenie: O(n)
  • Výhody: Jednoduchá implementácia.
  • Nevýhody: Pomalé vyhľadávanie, náročné na udržiavanie jedinečnosti prvkov.

Reprezentácia množiny pomocou spájaného zoznamu

Pri reprezentácii množiny pomocou spájaného zoznamu nie sú prvky uložené vedľa seba. Každý uzol obsahuje hodnotu a odkaz na ďalší prvok.

Schéma: [3 | • ] → [7 | • ] → [10 | • ] → None

  • Operácie:
  • Vloženie prvku: O(1) (na začiatok), ale pre množinu je nutné najprv overiť existenciu (O(n)).
  • Odstránenie prvku: O(n)
  • Vyhľadanie prvku: O(n)
  • Výhody: Dynamická veľkosť, jednoduché vkladanie prvkov (bez overenia duplicity).
  • Nevýhody: Pomalé vyhľadávanie.

Stromová reprezentácia množiny

Ako už bolo spomenuté, množiny sa často implementujú pomocou binárnych vyhľadávacích stromov (BST) alebo vyvážených stromov, ktoré ponúkajú efektívnejšie operácie s časovou zložitosťou O(log n).

Záver k dynamickým dátovým štruktúram a algoritmom

Pochopenie dynamických dátových štruktúr a algoritmov je nevyhnutné pre každého programátora a študenta informatiky. Tieto koncepty vám umožňujú efektívne riešiť problémy s dátami a písať optimálny kód. Či už ide o spájané zoznamy, stromy, grafy alebo triediace algoritmy, ich správne použitie vedie k výraznému zlepšeniu výkonu aplikácií.

Často kladené otázky (FAQ)

Čo sú dynamické dátové štruktúry a prečo sú dôležité?

Dynamické dátové štruktúry sú také, ktorých veľkosť sa môže meniť počas behu programu, čo umožňuje flexibilne pridávať alebo odoberať prvky. Sú dôležité, pretože sa používajú v prípadoch, keď dopredu nepoznáme presný počet prvkov, čím optimalizujú využitie pamäte a zjednodušujú správu dát.

Aký je rozdiel medzi jednosmerným a dvojito spájaným zoznamom?

Jednosmerný spájaný zoznam obsahuje vo vrchole odkaz iba na nasledujúci prvok, zatiaľ čo dvojito spájaný zoznam obsahuje odkaz na nasledujúci aj predchádzajúci prvok. Dvojito spájaný zoznam umožňuje prechádzať v oboch smeroch a uľahčuje operácie ako mazanie, ale potrebuje viac pamäte.

Kedy sa používa Merge Sort a kedy Quick Sort?

Merge Sort je stabilný triediaci algoritmus s časovou zložitosťou O(n log n) v každom prípade a vyžaduje dodatočnú pamäť O(n). Je vhodný pre veľké dáta a externé triedenie. Quick Sort je nestabilný algoritmus, v priemernom prípade tiež O(n log n), ale v najhoršom O(n²). Je veľmi rýchly v praxi pre interné triedenie a má lepšiu pamäťovú zložitosť O(log n).

Čo je to asymptotická zložitosť a prečo je relevantná?

Asymptotická zložitosť vyjadruje, ako sa čas behu algoritmu (alebo spotreba pamäte) mení s rastúcou veľkosťou vstupu (n). Je relevantná, pretože nám pomáha predpovedať správanie algoritmu pri spracovaní veľkých objemov dát a vybrať najefektívnejší algoritmus pre daný problém, nezávisle od konkrétnej implementácie alebo hardvéru.

Ako súvisí Huffmanov kód so stromovými štruktúrami?

Huffmanov kód používa binárny strom (Huffmanov strom) na efektívne kódovanie znakov. Strom je zostavený tak, že častejšie sa vyskytujúce znaky sú bližšie ku koreňu a dostávajú kratšie kódy (kód je tvorený cestou od koreňa k listu, kde ľavá hrana je 0 a pravá 1). Týmto spôsobom sa znižuje celková veľkosť uložených dát.

Sign up to access full content

Create a free account to unlock all study materials, take interactive tests, listen to podcasts and more.

Create free account

Súvisiace témy