Dynamick‚ çtrukt£ry £dajov
V predch dzaj£cich kapitol ch sme sa
stretli s viacerìmi çtrukt£rami £dajov, ktorìch ve–kosœ a umiestnenie
v operaŸnej pam„ti bola pevne deklarovan pred ich pou§it¡m. Boli to
napr¡klad polia a z znamy.
£dajov£ çtrukt£ru, ktorej rozsah sa poŸas jej existencie nemen¡, sa
nazìva statick £dajov
çtrukt£ra. Pri rieçen¡
niektorìch £loh vçak s£ vytv ran‚ çtrukt£ry, ktor‚ menia svoj rozsah, tieto
çtrukt£ry budeme nazìvaœ dynamick‚
£dajov‚ çtrukt£ry. Typickìm pr¡kladom dynamickej £dajovej çtrukt£ry je zoznam prvkov urŸit‚ho typu, na
ktorom je pou§¡van oper cia prid vania prvkov. Znamen to, §e zoznam zv„Ÿçuje
svoju ve–kosœ. Ak vieme ohraniŸiœ
poŸet prvkov zhora a vieme tie§, §e prid vanie sa uskutoŸåuje na jednom
konci zoznamu, tak je mo§n‚ pou§iœ na reprezent ciu zoznamu pole. Ak vçak pripust¡me prid vanie prvkov aj
doprostred zoznamu, potom reprezent cia pomocou po–a je nevìhodn , lebo
oper cia prid vania prvku bude vy§adovaœ posun mnohìch inìch prvkov
v poli, aby bolo vytvoren‚ miesto na ulo§enie nov‚ho prvku. Ak by bola
povolen oper cia vynech vania prvkov, tak by vznikli probl‚my s dierami
v poli.
Oper cie meniace rozsah dynamickej
£dajovej çtrukt£ry s£ efekt¡vnejçie realizovan‚, ak po§ijeme pre ich
reprezent ciu smern¡ky. Ka§dì prvok zoznamu je ulo§enì
v samostatnom objekte, ktor‚ho s£Ÿasœou je, okrem hodnoty prvku zoznamu,
tie§ polo§ka obsahuj£ca smern¡k (spoj, referenciu, odkaz) na objekt,
v ktorom je ulo§enì Ôalç¡ prvok zoznamu. Oper cia vlo§enia spoŸ¡va vo
vytvoren¡ objektu, ktorì obsahuje hodnotu nov‚ho prvku a smern¡k na
objekt, pred ktorì sa novì prvok zaraÔuje a v zmene smern¡ka
v tom objekte, za ktorì sa novì prvok zaraÔuje.
Reprezent cie dynamickìch £dajovìch çtrukt£r sa v jazyku PASCAL
vytv raj£ pomocou dynamickìch
premennìch a hodn“t typu smern¡k.
Dynamick‚
premenn‚ a typy smern¡k
Dynamickou premennou budeme rozumieœ tak£ premenn£, ktor nie je
zaveden v deklar cii premennìch, ale vznikne vykonan¡m çpeci lneho pr¡kazu.
Dynamick premenn nem pridelenì
identifik tor, ale identifikuje sa pomocou hodnoty zvl çtneho typu, ktor£
nazìvame smern¡k
a ktor£ m“§eme pova§ovaœ za abstrakciu adresy umiestnenia dynamickej
premennej v pam„ti. Pod–a typu dynamickìch premennìch rozliçujeme tie§
typy smern¡kov. Ka§dì typ smern¡k je viazanì na jeden typ dynamickìch premennìch, ktorì sa
nazìva dom‚novì typ
smern¡ka a je urŸenì v popise typu smern¡k.
Tento popis m tvar
^dom‚novì typ
Dom‚novìm typom m“§e byœ –ubovo–nì typ
a v popise typu smern¡k sa oznaŸuje identifik torom typu. Napr¡klad,
ak je v programe definovanì typ MENO,
potom pomocou deklar cie
type SMER=^MENO;
je definovanì typ SMER, ktor‚ho hodnotami s£ smern¡ky
identifikuj£ce dynamick‚ premenn‚ typu MENO.
V popise typu smern¡k m“§e byœ
pou§itì tie§ identifik tor typu, ktorì na danom nieste programu nie je eçte
definovanì. T to vìnimka je nutn
k tomu, aby bolo mo§n‚ definovaœ typy dynamickìch premennìch,
z ktorìch sa vytv raj£ smern¡kov‚ reprezent cie dynamickìch £dajovìch çtrukt£r.
Zvl çtnu hodnotu, ktor neidentifikuje §iadnu dynamick£ premenn£ a
ktor m“§e byœ priraden –ubovo–nej premennej typu smern¡k, je hodnota oznaŸen
k–£Ÿovìm slovom nil. Ak prirad¡me t£to hodnotu premennej P pr¡kazom
P:= nil,
tak premenn P neukazuje na §iadnu dynamick£ premenn£.
Ovl danie
vo–nej pam„ti
Premenn typu smern¡k obsahuje adresu v pam„ti dynamickej
premennej. Smern¡k je ulo§enì na dvoch slov ch a del¡ sa na offsetov£ a segmentov£ Ÿasœ.
Smern¡kovej premennej m“§eme priradiœ hodnotu troma sp“sobmi:
·
New(...),
·
oper torom @; @ je
un rny oper tor, ktorì vezme premenn£ alebo identifik tor proced£ry alebo
funkcie za operand a vr ti smern¡k k operandu; m“§e byœ priradenì –ubovo–nej
smern¡kovej premennej.
·
funkciou Ptr - function Ptr(segment, offset:word): pointer;
Proced£ry a
funkcie pre dynamick£ alok ciu:
·
Dispose(var p: pointer)
uvo–åuje dynamick£ premenn£, na ktor£ ukazuje premenn p; hodnota
smern¡ka po jej vykonan¡ zost va nedefinovan .
·
FreeMem(var p: pointer; size: word)
uvo–åuje pam„œ stanovenej ve–kosti; smern¡k mus¡ ukazovaœ na
dynamick£ premenn£, ktor bola vytvoren proced£rou GetMem; size urŸuje poŸet
uvo–åovanìch bytov.
·
GetMem(var p: pointer; size: word)
zaklad nov£ dynamick£ premenn£ uvedenej ve–kosti size (<=
65521) a ulo§¡ jej adresu do premennej p typu smern¡k.
·
Mark(var p: pointer)
zaznamen do premennej p aktu lnu adresu hromady (heap); t to
adresa m“§e byœ nesk“r vyu§it proced£rou Release;
p m“§e byœ smern¡k –ubovo–n‚ho typu.
·
MaxAvail: logint
vìsledkom je ve–kosœ maxim lnnej s£vislej pam„ti v hromade
s£hlas¡ s maxim lnou ve–kosœou dynamickej premennej, ktor£ je mo§n‚ alokovaœ.
·
MemAvail: logint
vìsledkom je ve–kosœ s£Ÿtu vçetkìch vo–nìch blokov pam„ti v hromade.
·
New(var p: pointer)
vytv ra nov£ dynamick£ premenn£ a nastavuje smern¡k na åu.
·
Release(var p: pointer)
vracia hromadu do stavu, pred ktorìm bola smern¡ku p priraden
hodnota proced£rou Mark;
uvo–åuje vçetky premenn‚ vytvoren‚ buÔ proced£rou New alebo GetMem, ktor‚ boli vytvoren‚ po
priraden¡ hodnoty smern¡ku p
proced£rou Mark.
Topologick‚
triedenie - TOPSORT
O topologickom trieden¡ hovor¡me
v s£vislosti s ŸiastoŸne usporiadanìmi mno§inami, na ktorìch je
definovan rel cia ŸiastoŸn‚ho usporiadania, t.j. takìch mno§¡n, v ktorìch
je definovan‚ usporiadanie len pre niektor‚ dvojice prvkov, (nemus¡ byœ pre
vçetky dvojice).
Matematick defin¡cia presne popisuje pojem ŸiastoŸne
usporiadan mno§ina}. ¬iastoŸn‚ usporiadanie mno§iny S je vo
vçeobecnosti dan‚ rel ciou medzi prvkami mno§iny $S$. Pre tri r“zne prvky x,
y, z patriace do mno§iny S t to rel cia sp’åa nasleduj£ce vlastnosti (axi¢my):
·
tranzit¡vnosœ:
Ak plat¡ x<y a y<z, tak plat¡ x<z.
·
antisymetria: Ak plat¡ x<y, tak neplat¡ y<x.
·
ireflex¡vnosœ:
Neplat¡ x<x.
Pr¡klady ŸiastoŸne usporiadanìch mno§¡n:
·
Matematickì pr¡klad
·
Slov v slovn¡ku
·
éloha rozdelen na
pod£lohy
·
Individu lny pl n
vìuŸby
·
V programoch
Z praktickìch d“vodov sa budeme zaoberaœ koneŸnìmi ŸiastoŸne usporiadanìmi mno§inami.
¬iastoŸne usporiadan‚ mno§iny m“§eme zobraziœ n zorne pomocou
grafov. Prvky mno§iny bud£ ulo§en‚ vo vrcholoch a pomocou orientovanìch hr n
vyjadr¡me smer usporiadania.
Probl‚m topologick‚ho triedenia spoŸ¡va vo
vnoren¡ ŸiastoŸn‚ho usporiadania do line rneho usporiadania. Graficky to znamen , §e vrcholy grafu
(prvky mno§iny) nakresl¡me do radu a vçetky ç¡pky hr n bud£ smerovaœ
jednìm smerom. Vlastnosti ŸiastoŸne usporiadanej mno§iny zaruŸuj£, §e graf
neobsahuje §iadne cykly.
Postup pri h–adan¡ jedn‚ho z mo§nìch
rieçen¡ je ve–mi jednoduchì a m“§eme ho vyjadriœ takto: ZaŸneme vìberom
prvkov, ktorìm nepredch dza §iadny inì prvok (mus¡ byœ aspoå jeden, preto§e
inak by graf obsahoval cyklus).
Tieto prvky odstr nime z mno§iny $S a zarad¡me ich do
vytv ran‚ho zoznamu, reprezentuj£ceho line rne usporiadanie. Zost vaj£ca
mno§ina je st le ŸiastoŸne usporiadan , a preto m“§eme na åu aplikovaœ ten
istì algoritmus a§ dovtedy, kìm nebude pr zdna.
Aby sme tento algoritmus mohli presnejçie zap¡saœ, mus¡me sa
rozhodn£œ o sp“sobe reprezent cie mno§iny a ŸiastoŸn‚ho usporiadania.
Ka§dì prvok m“§eme charakterizovaœ pomocou troch atrib£tov: identifikaŸn‚ho
k–£Ÿa (kluc), mno§iny nasledovn¡kov (smern¡k priv) a celkov‚ho poŸtu
predchodcov (pocit)}. Prvky spoj¡me do line rneho zoznamu prepojen‚ho
smern¡kom dalsi. Budeme
predpokladaœ, §e k–£Ÿe s£ vyjadren‚ celoŸ¡selnìmi hodnotami (ale nie nutne po
sebe id£cimi Ÿ¡slami 1 a§ n). Zoznam nasledovn¡kov bude tie§ line rny zoznam
pripojenì k dan‚mu prvku pomocou smern¡ka
priv. Prvok v tomto zozname bude teda ukazovaœ na nasledovn¡ka
pomocou smern¡ka vrch a na
Ôalç¡ prvok tohto zoznamu pomocou smern¡ka dalsi. Teda odpovedaj£ce typy £dajov
bud£ maœ nasleduj£ci tvar:
Type
psmer = ^vrchol;
lsmer = ^prives;
vrchol = record
kluc:hodnota;
pocit:integer;
dalsi:psmer;
priv:lsmer;
end;
prives = record
vrch:psmer;
dalsi:lsmer;
end;
Celì program m“§e maœ nasleduj£ci tvar:
program
TOPSORT;
type
hodnota = integer;
psmer = ^vrchol;
lsmer = ^prives;
vrchol = record
kluc:hodnota;
pocit:integer;
dalsi:psmer;
priv:lsmer;
end;
prives = record
vrch:psmer;
dalsi:lsmer;
end;
var
hlava, chvost, p,
q:psmer;
t:lsmer;
z:integer;
ff:text;
x, y:hodnota;
function
l(w:hodnota):psmer;
{Hodnotou
funkcie je smernik k vrcholu, v ktorom je ulozene w}
var
h:psmer;
begin
h:=hlava;
chvost^.kluc:=w;
{Ulozenie zarazky}
while
h^.kluc<>w do h:=h^.dalsi;
if h=chvost then
begin
{Ziadny prvok s
hodnotou w nebol ulozeny}
new(chvost);
z:=z+1;
chvost^.pocit:=0; chvost^.dalsi:=nil;
chvost^.priv:=nil;
h^.dalsi:=chvost;
end;
l:=h
end;
{Koniec funkcie l}
begin
{
Vytvorenie prazdnej struktury}
z:=0;
new(hlava); chvost:=hlava;
with
hlava^ do
begin
dalsi:=nil; priv:=nil; pocit:=0; end;
{Vstupna
faza}
assign(ff,'tpsort.dta'); rewrite(ff);
read(x);
while
x<>0 do
begin
readln(y); writeln(ff,'x= ',x:3,'=> y= ',y:3);
p:=l(x); q:=l(y);
new(t);
t^.dalsi:=p^.priv; t^.vrch:=q;
p^.priv:=t; inc(q^.pocit);
read(x)
end;
{Hladanie
clenov s nulovym poctom predchodcov}
p:=hlava; hlava:=nil;
while
p<>chvost do
begin
q:=p; p:=p^.dalsi;
if q^.pocit=0 then
begin
q^.dalsi:=hlava; hlava:=q;
end;
end;
writeln('Pocet vrcholov je ',z:3);
{Vystupna
faza}
q:=hlava;
while
q<>nil do
begin
writeln(q^.kluc); writeln(ff,q^.kluc);
z:=z-1;
t:=q^.priv; q:=q^.dalsi;
while t<>nil do
begin
p:=t^.vrch; dec(p^.pocit);
if p^.pocit = 0 then
begin
{Ulozenie
do zoznamu prvkov s nulovym poctom predchodcov}
p^.dalsi:=q; q:=p;
end;
t:=t^.dalsi;
end;
end;
if
z<>0 then
begin
writeln(' Tato mnozina nie je ciastocne usporiadana');
writeln(ff,'Tato mnozina nie je ciastocne usporiadana')
end;
close(ff);
readln;
end.