300 likes | 483 Views
Adatszerkezetek. Adattípusok ábrázolása. Absztrakt adattípus (ADT) Algebrai specifikáció Funkcionális specifikáció Absztrakt adatszerkezet (ADS) Reprezentáció (ábrázolás) Aritmetikai (tömbös) ábrázolás Láncolt (pointeres) ábrázolás. Absztrakt adattípus (ADT).
E N D
Adattípusok ábrázolása • Absztrakt adattípus (ADT) • Algebrai specifikáció • Funkcionális specifikáció • Absztrakt adatszerkezet (ADS) • Reprezentáció (ábrázolás) • Aritmetikai (tömbös) ábrázolás • Láncolt (pointeres) ábrázolás
Absztrakt adattípus (ADT) • Ez a szint az adattípus leírásának legmagasabb absztrakciós szintje. • Az adattípust úgy specifikáljuk, hogy szerkezetére, reprezentálására, implementálására semmilyen megfontolást, előírást, utalást nem teszünk. • A leírásban kizárólag matematikai fogalmak használható • Az ADT szintű leírás lehet formális, és lehet informális is: • pl. természetes magyar nyelven is elmondhatjuk, hogy mit várunk el egy veremtől. • A lényeg nem a formalizáltság mértéke, hanem az, hogy „nem látjuk” az adattípus belső struktúráját.
Absztrakt adattípus (ADT) • Alapvetően két leírási mód terjedt el: • algebrai specifikáció (axiómák megadásával), • funkcionális specifikáció (elő- és utófeltétellel).
algebrai specifikáció (axiómák megadásával) • Példa: Az E alaptípus feletti V verem absztrakt adattípus (ADT) axiomatikus jellemzése három lépésben. A verem „lényege” az, hogy a legutoljára betett elemet lehet kivenni belőle. • 1. Műveletek (mint leképezések) • Empty: V Üres verem konstans; az üres verem „létrehozása” • IsEmpty: VL A verem üres voltának lekérdezése • Push: VEV Elem betétele a verembe • Pop: VVE Elem kivétele a veremből • Top: VE A felső elem lekérdezése • 2. Megszorítások a műveletekre (értelmezési tartományok) • Az üres veremből nem lehet elemet kivenni, és a felső elemét sem lehet lekérdezni. • DPop = V \ {Empty} • DTop = V \ {Empty}
algebrai specifikáció (axiómák megadásával) • 3. Axiómák • IsEmpty(Empty) vagy v = EmptyIsEmpty(v) • IsEmpty(v) v = Empty • ¬IsEmpty(Push(v,e)) • Pop(Push(v,e)) = (v,e) • Push(Pop(v)) = v • Top(Push(v,e)) = e • Az axiómákat úgy írjuk fel, hogy sorra vesszük az öt művelet (ill. egy konstans és négy művelet) összes lehetséges párosítását – mindkét sorrendben –, és ha van értelme az adott egymásra hatásnak, akkor azt kifejezzük egy logikai állítással.
Absztrakt adatszerkezet (ADS) • Az ADS szinten egy fontos döntést hozunk meg az ADT szintű specifikáció alapján. • Megmondjuk azt, hogy alapvetően milyen struktúrája van a szóban forgó adattípusnak. • Közelebbről ez azt jelenti, hogy megadjuk az adatelem közötti legfontosabb rákövetkezési kapcsolatot, és ezt egy irányított gráf formájában le is rajzoljuk. • Az ADS szintet egy szerkezeti gráf és az ADT szinten bevezetett műveletek alkotják együttesen.
Absztrakt adatszerkezet (ADS) • Az adatszerkezeteket osztályozhatjuk az általuk meghatározott gráf alakja szerint: • lineáris, • kétirányú vagy szimmetrikus lineáris, • fa (struktúrájú), • ortogonális (pl. mátrix) • többszörösen összefüggő = általános gráf alakú adatszerkezet.
Reprezentációs szint • Ezen a szinten arról hozunk döntést, hogy az ADS-szinten megjelent gráf rákövetkezési relációit milyen módon ábrázoljuk. • Az ábrázolás még mindig absztrakt, noha már a számítógépes megvalósítást modellezi. • Két tiszta reprezentálási mód van, illetve ezeket lehet vegyesen is alkalmazni: • aritmetikai (tömbös) ábrázolás, • láncolt (pointeres) ábrázolás.
Aritmetikai ábrázolás • A memóriát úgy képzeljük el, mint egy hosszú, egydimenziós tömböt, vagyis vektort, amelynek elemei byte-ok. Ezen alapul az aritmetikai ábrázolás első változata. • Címfüggvényes aritmetikai ábrázolás: • az absztrakt memória-vektor adott kezdőcímétől kezdve elhelyezzük az adott adatszerkezet elemeit. • Egy adatelem több byte-ot is elfoglalhat. Meg kell adni a címfüggvényt, amelynek segítségével minden adatelem helye (címe) meghatározható. • Indexfüggvényes aritmetikai ábrázolás: • ez az absztraktabb ábrázolás. • Az adatszerkezet elemeit egy olyan tömbben helyezzük el, amelynek nem byte-ok az elemei, hanem az adatszerkezet alaptípusának példányai. • Az elhelyezést az első elemtől kezdjük, és ekkor egy indexfüggvényt kell megadnunk
Reprezentációs szint • Láncolt ábrázolás • Ehhez az ábrázoláshoz bevezetjük az absztrakt mutató (pointer) fogalmát. • Ha p egy mutató típusú változó, akkor pˆ jelöli az általa mutatott adatelemet. • Ennek az adatelemnek az esetleges komponenseit (pl. adat és mutató) pˆ.adat, ill. pˆ.mut jelöli. • A sehová sem mutató pointer értéke NIL
Tömbök • ADT • Legyen T egy E alaptípus feletti k (≥ 1) dimenziós tömb típus. Vezessük be az indexhalmazt, ahol • Műveletek (melyek bármely k esetén szerepelnek): indexelés (=tömbelem kiválasztása) a már bevezetett A[i1,i2,…,ik] kifejezéssel, ami szerepelhet értékadó utasítás bal oldalán, és jobb oldalán is. Így lehetséges: • tömbelem lekérdezése, • tömbelem módosítása.
Tömbök • ADS • Az a megegyezés született, hogy j szerinti rákövetkezést is definiálnak: kövjA[i1,…,ij,….ik] = A[i1,…,ij+1,…,ik] • Minden belső elemnek k db rákövetkezője van (azért csak a belsőknek, mert definíció szerint a dimenzió határánál nincs rákövetkező).
Verem • A mindennapok során gyakran találkozunk a verem tároló struktúrával. • Legismertebb példa a névadó, a mezőgazdaságban használt verem. • Több távolsági buszon is a vezető a különböző pénzérméket egy-egy kis verembe tudja betenni, ill. azokból veszi elő. • A kávéházakban az alátét tányérokat gyakran egy veremként működő tároló mélyedésben tartják, stb.
Verem ADT • Műveletek: • Empty: V Üres verem konstans; az üres verem „létrehozása” • IsEmpty: VL A verem üres voltának lekérdezése • Push: VEV Elem betétele a verembe • Pop: VVE Elem kivétele a veremből • Top: VE A felső elem lekérdezése • Megszorítások: • DPop = DTop = V \ {Empty}
Verem • Algebrai specifikáció: • IsEmpty (Empty) vagy v = EmptyIsEmpty(v) • IsEmpty (v) v = Empty • ¬IsEmpty (Push(v,e)) • Pop (Push(v,e)) = (v,e) • Push (Pop(v)) = v • Top (Push(v,e)) = e
Verem • Aritmetikai ábrázolás • Bevezetjük a top változót, mely mindig a legfelső elem indexe (top [0..max]). • A v vermet ábrázoló tömb: v[1..max]. • A szokásos műveletek mellett használni kell egy új, IsFull műveletet is, mivel a tömb betelhet, és ezt figyelni kell.
program verem; uses crt; var v:array [1.. 10]of integer; mut: integer; function urese:boolean; begin urese:=(mut=0); end; function pop:integer; begin if not urese then begin pop:=v[mut]; mut:=mut-1; end; end; function top:integer; begin if not urese then top:=v[mut]; end; procedure push(e:integer); begin if mut < 10 then {azért 10 mert ekkora a tömb} begin mut:=mut+1; v[mut]:=e; end; end; procedure kiir; begin while not urese do write(pop); writeln; end; BEGIN push(1);push(12);push(14);kiir;pop;kiir; END. Verem egy megvalósítása
Verem alkalmazásai • A verem adatszerkezetnek számos alkalmazásával találkozhatunk az algoritmusok és programok világában. • Alapvetően egy sorozat megfordítására alkalmas: ABCD DCBA. • Ha azonban a verembe írást és a kivételt nem elkülönítve, egymás után, hanem „összekeverve” alkalmazzuk, akkor a sorozat számos átrendezését meg tudjuk valósítani
Sor ADT • Műveletek: • Empty: S Üres sor konstans; az üres sor „létrehozása” • IsEmpty: SL A sor üres voltának lekérdezése • In: SES Elem betétele a sorba • Out: SSE Elem kivétele a sorból • First: SE Az első elem lekérdezése • Megszorítások: • DOut = DFirst = S \ {Empty}
Sor • Algebrai specifikáció: • IsEmpty(Empty) vagy s = EmptyIsEmpty(s) • IsEmpty(s) s = Empty • ¬IsEmpty(In(s,e)) • Out(In(Empty,e)) = (Empty,e) • ¬IsEmpty(s) Out(In(s,e))2 = Out(s)2 • ¬IsEmpty(s) In(Out(s)1,e) = Out(In(s,e))1 • First(s) = Out(s)1 • Itt az 1-es, illetve a 2-es index a pár első, illetve második komponensét jelöli.
Sor • ADS • A sor a veremhez hasonlóan lineáris adatszerkezet • Aritmetikai ábrázolás: • Az s sor ebben az ábrázolásban egy rekordszerkezet, melynek része egy s[1..max] tömb, amely a sor elemeit tartalmazza • egy e{1 , … , max} index, amely mindenkor az első elemre mutat • valamint egy k{0 , … , max} változó, amely a sor elemszámát jelzi.
Sor • A sor úgy működik, hogy a sor végére rakjuk, ill. az elejéről veszünk ki az elemeket. • Ezért célszerű a tömb elejére „beengedni” a tömb végén „kilógó” elemeket, különben betelne úgy a tömb, hogy egyes indexei felhasználatlanok. • Egy tipikus sor lassan „körbemegy” a tömbön.
Sor • A sor alkalmazásai • Egyes pufferelési eljárásokban (pl. klaviatúránál). • Gráfok, ill. fák szélességi bejárásánál (pl. bináris fák szintfolytonos bejárása, lásd ott!). • Elméleti érdekesség: a sor „körbetekerésével” szimulálható a verem adatszerkezet, de a sor csak két veremmel valósítható meg.
Sor egy megvalósítása type elemtip=integer; elem=^selem; selem=record ertek:elemtip; mut:elem; end; sor=record eleje,vege:elem; {elsonek es utolsonak betett elem} hossz:integer; hiba:boolean; end;
Sor egy megvalósítása procedure ures(var s:sor); begin s.eleje:=nil; s.vege:=nil; s.hossz:=0; s.hiba:=false; end; function ures_e(var s:sor):boolean; begin ures_e:=(s.hossz=0); end;
Sor egy megvalósítása function tele_e(var s:sor):boolean; begin if (s.hossz < 20) then tele_e:=false else tele_e:=true; end; function elso(var s:sor):elemtip; begin if ures_e(s) then s.hiba:=true else elso:=s.eleje^.ertek; end;
Sor egy megvalósítása procedure sorba(var s:sor; e:elemtip); var uj:elem; begin if tele_e(s) then s.hiba:=true else begin new(uj); uj^.ertek:=e; uj^.mut:=nil; s.hossz:=s.hossz+1; if s.vege=nil then begin s.eleje:=uj; s.vege:=uj end else begin s.vege^.mut:=uj; s.vege:=uj end end; end;
Sor egy megvalósítása procedure sorbol(var s:sor; var e:elemtip); var se:elem; begin if ures_e(s) then s.hiba:=true else begin e:=s.eleje^.ertek; se:=s.eleje; s.eleje:=se^.mut; dispose(se); s.hossz:=s.hossz-1; if s.eleje=nil then s.vege:=nil; end; end;
Sor egy megvalósítása function hibas_e(var s:sor):boolean; begin hibas_e:=(s.hiba=true); s.hiba:=false; end;