Cvičenie č. 10 - Zásobník a fronta (stack and queue)
Zásobník (stack) a fronta (queue) sú jedny zo základných dátových štruktúr, ktoré sa používaju k dočasnému ukladaniu dát. Tieto štruktúry taktiež určujú poradie spracovávania dát, ktoré obsahujú.
Z fronty dáta vystupujú v rovnakom poradí, v akom do nej vstúpili. Takejto štruktúre sa bežne hovorí FIFO - First In First Out. V podstate funguje rovnako ako fronta v obchodoch :).
Zo zásobníku naopak vystupujú vždy najprv dáta, ktoré doň boli vložené naposledy. Takejto štruktúre sa zas hovorí LIFO - Last In First Out. Predstavte si dieru, do ktorej postupne hádžete nejaké veci, vždy keď z nej chcete niečo vybrať, tak musíte začat najprv vecou, ktorá sa práve nachádza na vrchu.
Použitie: prehľadávanie grafov alebo stavového priestoru, vyhodnocovanie aritmetických výrazov atď.
Zásobník
Na vytvorenie zásobníku potrebujete len nejaký zoznam alebo pole, do ktorého si budete ukladať jednotlivé prvky a nejakú premennú, v ktorej si budete udržovať aktuálny počet uložených prvkov. Nad touto dátovou štruktúrou potom musíte definovať operácie, ktoré budú dodržovať vlastnosti zásobníku.
Ako môže vyzerať zásobník napr. v Pascale:
program stack;
{ znovu budeme predpokladat, ze nas zasobnik nebude obsahovat viac
nez nejaky konstanty pocet prvkov }
const MAX = 1000;
type TData = char; { typ dat ktore budeme do zasobniku vkladat}
{ Na reprezentaciu zasobniku pouzijeme typ record (struktura),
ktora sa pouziva na zoskupovanie niekolkych premennych.
K jednotlivm premennym sa potom dostaneme pomocou .
Napr. var rec: TStack;
rec.size = 10; }
type TStack = record
items: array[1..MAX] of TData; { obsah zasobniku}
size: 0..MAX; { pocet prvkov v zasobniku }
end;
{ vrati True ak je zasobnik prazdny, inak False }
function isEmpty(var stack: TStack): boolean;
{ zinicializuje prazdny zasobnik}
procedure init(var stack: TStack);
{ vlozi jeden prvok na vrch zasobniku }
procedure push(var stack: TStack; item: TData);
{ vráti prvok z vrchu zasobnika (ale neodstrani) }
function peek(var stack: TStack): TData;
{ vrati a odstrani prvok z vrchu zasobnika }
function pop(var stack: TStack): TData;Poznámka: Fronta by sa dala reprezentovať úplne rovnako, akurát by bolo treba trochu upraviť implementáciu procedúr push a pop.
Úloha 1: Naimplementujte si zásobník
Doimplementujte funkcie a procedúry z príkladu vyššie.
Úloha 2: Uzátvorkovanie druhýkrát
Napíšte funkciu checkParenthesis, ktorá skontroluje, že uzátvorkovanie vstupného reťazca je správne. Reťazec tentokrát môže obsahovať až 3 typy zátvoriek: ()[]{} a otvorená zátvorka jedného typu môže byť ukončená len opačnou zátvorkou rovnakého typu. Na riešenie úlohy použite zásobník z predchádzajúcej úlohy.
Príklady:
Vstup: '{()}[]'
Výstup: TrueVstup: '{()][]'
Výstup: FalseVstup: '{()[]'
Výstup: FalsePrefixový vs infixový vs postfixový zápis aritmetického výrazu
Bežnému vyjadreniu aritmetických výrazov napr.:
(5 + ((1 + 2) * 4)) sa hovorí infixový zápis, pretože operátor sa vždy nachádza medzi (in) operandami. Alternatívne môžme ten istý výraz vyjadriť v postfixovom zápise ako:
5 1 2 + 4 * + alebo v prefixovom zápise ako:
+ 5 * + 1 2 4 Prefixový alebo postfixový zápis je narozdiel od infixového jednoznačný a preto u nich odpadáva potreba definovať prioritu operátorov alebo zátvorky. To samozrejme zjendodušuje ich strojové spracovanie.
Prefixovému zápisu sa tiež hovorí poľská notácia.
Bonusová úloha: Vyhodnotenie výrazu v poľskej notácii
Napíšte funkciu evalExpression, ktorá dostane na vstup výraz v poľskej notácii ako reťazec a ona vráti jeho hodnotu. Napr.: pre vstup + 1 2 vráti hodnotu 3.
Hint: Použite zásobník :)
Počet bodov: 20
Odovzdanie: mailom do 6. 13. 2016 (23:59)
Prehľadávanie grafu
Z prednášky by ste už mali vedieť čo je to prehľadávanie do širky - Breadth-first search (BFS) a prehľadávanie do hĺbky - Depth-first search (DFS).
Pre pripomenutie:
BFS:

DFS:

Vezmime si tento pseudokód prehľadávania grafu:
graph - nejaka reprezentacia grafu
root - vrchol v ktorom zacneme prehladavanie
{ inicializacia pomocnych premennych }
for each node n in graph:
{ u kazdeho vrcholu si poznacime ci sme ho uz videli }
n.visited := False
c := empty Collection { prazdna kolekcia ktoru si este dodefinujeme }
root.visited := True
push(c, root)
while not isEmpty(c):
current := pop(c)
for each node n that is adjacent to current:
if not n.visited:
n.visited := True
push(c, n)Aké prehľadávanie dostaneme, ak si za Collection dosadíme zásobník a aké ak frontu?
Domáca úloha
V CodEx-e nájdete svoju domácu úlohu: Kyblík.
Hint: Použite napr. prehľadávanie do šírky.
Poznámka: Tentokrát máte vstup načítať zo súboru bitmap.in, nie zo štandardného vstupu. Pre prácu so súbormi viz. Cvičenie č. 4.
Termín odovzdania: 13. 12. 2016 (23:59)