Cvičenie č. 12 - Správa pamäte & binárne vyhľadávacie stromy
Na poslednej hodine sme si zaviedli ukazatele a funkciu new, ktorá je schopná naalakovať premennú daného typu na halde. Čo sa však stane, ak naalokovanú premennú už nepotrebujeme, ako napríklad u operácii remove spojového zoznamu? Túto pamäť musíme ručne uvolniť (dealokovať) funkciou dispose, ktorá na vstup dostane tiež ukazateľ.
Ak však stratíme ukazateľ pred uvoľnením pamäte, tak táto časť pamäte ostane nepoužiteľná až do ukončenia programu. Takáto chyba vedie často k výnimkám typu Out Of Memory Exception (OOM), kedy si zaplníme celú haldu nepoužívanými premennými. Tomuto sa medzi programátormi hovorí tiež leak-ovanie pamäte.
Platí nasledujúce jednoduché pravidlo: s každým zavolaním funkcie new musí byť spárované zavolanie funkcie dospose.
V letnom semestri začenete používať jazyk C#, ktorý sa o správu pamäte stará sám, tzn. žiadna funkcia dispose u neho nie je potrebná.
Binárne vyhľadávacie stromy (BST - z angl. Binary Search Tree)
Binárny vyhľadávací strom je dynamická dátová štruktúra založená na binárnom strome, v ktorom sú jednotlivé prvky (uzly) usporiadané tak, aby v ňom bolo možné rýchlo vyhľadávať. Tento strom má nasledujúce vlastnosti:
- každý uzol má maximálne 2 potomkov - ľavého a pravého syna
- každý uzol obsahuje hodnotu alebo kľúč, ktorý chceme vyhľadávať a určuje usporiadanie uzlov
- pre každý uzol v strome platí, že ľavý resp. pravý podstrom obsahuje len kľúče menšie resp. väčšie než je kľúč aktuálneho uzlu
Základné operácie BST:
- insert - vloženie nového prvku
- member - zistenie či sa prvok s danou hodnotou nachádza v strome
- delete - odstránenie prvku zo stromu
Pekná vizualizácia fungovania BST tu.
Na zamyslenie:
- Aká je časová zložitosť operácií insert, delete, member?
- Ako súvisí binárne vyhľadávanie v zotriedenom poli s BST?
Prehľadávanie stromu do hĺbky
Podľa poradia v akom prechádzame uzly v strome môžeme definovať tieto 3 typy prehľadávania:
PREORDER
- vykonaj akciu
- prejdi ľavý podstrom
- prejdi pravý podstrom
INORDER
- prejdi ľavý podstrom
- vykonaj akciu
- prejdi pravý podstrom
POSTORDER
- prejdi ľavý podstrom
- prejdi pravý podstrom
- vykonaj akciu
Príklad:

Ak definujeme akciu vypísaním hodnoty uzlu, tak dostaneme tieto výstupy:
- Inorder: A, B, C, D, E, F, G, H, I
- Preorder: F, B, A, D, C, E, G, I, H
- Postorder: A, C, E, D, B, H, I, G, F
Naimplementujte BST
Nižšie môžete vidieť jeden z možných spôsobov definovania BST v pascale. Vašou úlohou je znovu domplementovať chýbajúce základné operácie nad BST.
program bst;
type TData = integer;
TNode = record
data: TData;
left: ^TNode;
right: ^TNode;
end;
TBinaryTree = record
root: ^TNode;
end;
{ zinicializuje novy strom }
procedure init(var tree: TBinaryTree);
begin
end;
{ vykresli strom v peknom formate, napr: }
{ 2
/ \
/ \
/ \
/ \
7 5
/ \ \
/ \ \
2 6 9
/ \ /
5 8 4
}
procedure pretty_print(var tree: TBinaryTree);
begin
end;
{ vlozi novy prvok do stromu }
procedure insert(var tree: TBinaryTree; val: TData);
begin
end;
{ vrati true ak sa dany prvok v strome nachadza inak false }
function member(var tree: TBinaryTree; val: TData): boolean;
begin
end;
{ odstrani dany prvok zo stromu (pouzite spravne dispose!)}
procedure remove(var tree: TBinaryTree; val: TData);
begin
end;
{ vrati pocet uzlov v strome }
function size(var tree: TBinaryTree): integer;
begin
end;
{ zmaze cely strom (pouzite dispose!) }
procedure delete(var tree: TBinaryTree);
begin
end;
{ vypise hodnoty uzlov v strome v preorder poradi }
procedure print_preorder(var tree: TBinaryTree);
begin
end;
{ vypise hodnoty uzlov v strome v inorder poradi }
procedure print_inorder(var tree: TBinaryTree);
begin
end;
{ vypise hodnoty uzlov v strome v inorder poradi }
procedure print_post(var tree: TBinaryTree);
begin
end;Bonusová domáca úloha
Hlavne pre tých, čo nemajú dosť bodov z domácich úloh.
Doimplementujte všetky operácie nad BST definovaných vyšše.
Termín odovzdania: 4. 1. 2017 (23:59)
Spôsob odovzdania: zdrojový kód mailom
Počet bodov: 50