Például számokból álló, egyszeresen láncolt lista felépítéséhez az alábbi struktúra definíciót használhatjuk:



Hasonló dokumentumok
Programozás I gyakorlat

Mutatók és címek (ism.) Programozás alapjai C nyelv 8. gyakorlat. Indirekció (ism) Néhány dolog érthetőbb (ism.) Változók a memóriában

Algoritmusok és adatszerkezetek gyakorlat 06 Adatszerkezetek

Információs Technológia

Programozás alapjai C nyelv 8. gyakorlat. Mutatók és címek (ism.) Indirekció (ism)

A programozás alapjai előadás. [<struktúra változó azonosítók>] ; Dinamikus adatszerkezetek:

Adatszerkezetek I. 8. előadás. (Horváth Gyula anyagai felhasználásával)

10. előadás Speciális többágú fák

Miről lesz ma szó? A PROGAMOZÁS ALAPJAI 1. Dinamikus adatszerkezetek. Dinamikus adatszerkezetek. Önhivatkozó struktúrák. Önhivatkozó struktúrák

Tartalom Keresés és rendezés. Vektoralgoritmusok. 1. fejezet. Keresés adatvektorban. A programozás alapjai I.

Programozás alapjai II. (7. ea) C++ Speciális adatszerkezetek. Tömbök. Kiegészítő anyag: speciális adatszerkezetek

Keresés és rendezés. A programozás alapjai I. Hálózati Rendszerek és Szolgáltatások Tanszék Farkas Balázs, Fiala Péter, Vitéz András, Zsóka Zoltán

Speciális adatszerkezetek. Programozás alapjai II. (8. ea) C++ Tömbök. Tömbök/2. N dimenziós tömb. Nagyméretű ritka tömbök

Programozás alapjai II. (7. ea) C++

Programozás alapjai C nyelv 5. gyakorlat. Írjunk ki fordítva! Írjunk ki fordítva! (3)

file:///d:/okt/ad/jegyzet/ad1/b+fa.html

Elemi adatszerkezetek

Láncolt lista. az itt adott nevet csak a struct deklaráción belül használjuk

Algoritmusok és adatszerkezetek gyakorlat 07

Adatszerkezetek és algoritmusok

10. gyakorlat Struktúrák, uniók, típusdefiníciók

Egyirányban láncolt lista

Adatszerkezetek I. 7. előadás. (Horváth Gyula anyagai felhasználásával)

C programozási nyelv Pointerek, tömbök, pointer aritmetika

A számítástudomány alapjai. Katona Gyula Y. Számítástudományi és Információelméleti Tanszék Budapesti Műszaki és Gazdaságtudományi Egyetem

7. BINÁRIS FÁK 7.1. A bináris fa absztrakt adattípus 7.2. A bináris fa absztrakt adatszerkezet

Láncolt listák. Egyszerű, rendezett és speciális láncolt listák. Programozás II. előadás. Szénási Sándor

Amortizációs költségelemzés

Programozas 1. Strukturak, mutatok

A C programozási nyelv V. Struktúra Dinamikus memóriakezelés

5. Gyakorlat. struct diak {

A lista adatszerkezet A lista elemek egymásutániságát jelenti. Fajtái: statikus, dinamikus lista.

7 7, ,22 13,22 13, ,28

6. gyakorlat Egydimenziós numerikus tömbök kezelése, tömbi algoritmusok

Adatszerkezetek 1. előadás

Láncolt listák Témakörök. Lista alapfogalmak

Struktúrák (struct) A struktúra szerkezetét meghatározó deklaráció általános formája:

B-fa. Felépítés, alapvető műveletek. Programozás II. előadás. Szénási Sándor.

11. gyakorlat Sturktúrák használata. 1. Definiáljon dátum típust. Olvasson be két dátumot, és határozza meg melyik a régebbi.

Programozás alapjai C nyelv 9. gyakorlat. Rekurzió. Rekurzív algoritmus

Programozás I gyakorlat. 10. Stringek, mutatók

C memóriakezelés. Mutató típusú változót egy típus és a változó neve elé írt csillag karakterrel hozhatjuk létre.

Óbudai Egyetem. C programozási nyelv

C programozási nyelv

17. A 2-3 fák és B-fák. 2-3 fák

OOP #14 (referencia-elv)

Adatszerkezetek 7a. Dr. IványiPéter

Rekurzió. Programozás alapjai C nyelv 9. gyakorlat. Rekurzív algoritmus. Rekurzív algoritmus fajtái. Példa: n! (2) Példa: n!

Operációs rendszerek. 11. gyakorlat. AWK - szintaxis, vezérlési szerkezetek UNIVERSITAS SCIENTIARUM SZEGEDIENSIS UNIVERSITY OF SZEGED

Függvények. Programozás alapjai C nyelv 7. gyakorlat. LNKO függvény. Függvények(2) LNKO függvény (2) LNKO függvény (3)

Programozás alapjai C nyelv 7. gyakorlat. Függvények. Függvények(2)

Adatszerkezetek 1. Dr. Iványi Péter

C++ programozási nyelv

Ugrólisták. RSL Insert Example. insert(22) with 3 flips. Runtime?

Mutatók és mutató-aritmetika C-ben március 19.

Hierarchikus adatszerkezetek

file:///d:/apa/okt/ad/jegyzet/ad1/b+fa.html

Láncolt Listák. Adat1 Adat2 Adat3 ø. Adat1 Adat2 ø Adat3

félstatikus adatszerkezetek: verem, várakozási sor, hasítótábla dinamikus adatszerkezetek: lineáris lista, fa, hálózat

Táblázatok fontosabb műveletei 1

8. gyakorlat Pointerek, dinamikus memóriakezelés

Példa 30 14, 22 55,

tétel: különböző típusú adatokat csoportosít, ezeket egyetlen adatként kezeli, de hozzáférhetünk az elemeihez is

Adatszerkezetek Adatszerkezet fogalma. Az értékhalmaz struktúrája

C++ programozási nyelv Struktúrák a C++ nyelvben

Információs Technológia

Adatbázisrendszerek I. File-szintű adattárolás C-ben. 1. gyakorlat

Mit tudunk már? Programozás alapjai C nyelv 4. gyakorlat. Legnagyobb elem keresése. Feltételes operátor (?:) Legnagyobb elem keresése (3)

C programozási nyelv

1. Egyszerű (primitív) típusok. 2. Referencia típusok

Rekurzió. Dr. Iványi Péter

Programozás alapjai C nyelv 4. gyakorlat. Mit tudunk már? Feltételes operátor (?:) Típus fogalma char, int, float, double

Web-programozó Web-programozó

10. tétel. Adatszerkezetek és algoritmusok vizsga Frissült: január 28.

Algoritmusok és adatszerkezetek I. 1. előadás

Programozás II. 2. Dr. Iványi Péter

Algoritmuselmélet. 2-3 fák. Katona Gyula Y. Számítástudományi és Információelméleti Tanszék Budapesti Műszaki és Gazdaságtudományi Egyetem. 8.

INFORMATIKA javítókulcs 2016

Absztrakt adatstruktúrák A bináris fák

Láncolt listák. PPT 2007/2008 tavasz.

Járműfedélzeti rendszerek II. 4. előadás Dr. Bécsi Tamás

5. SOR. Üres: S Sorba: S E S Sorból: S S E Első: S E

Fák Témakörök. Fa definíciója. Rekurzív típusok, fa adatszerkezet Bináris keresőfa, bejárások Bináris keresőfa, módosítás B-fa

C programozás. { Márton Gyöngyvér, 2009 } { Sapientia, Erdélyi Magyar Tudományegyetem }

A C# programozási nyelv alapjai

Miről lesz ma szó? A PROGAMOZÁS ALAPJAI 1. Dinamikus változók. Dinamikus változók. Dinamikus változók. Dinamikus változók. 7.

Programozás II. 4. Dr. Iványi Péter

Programozás 5. Dr. Iványi Péter

Fejlett programozási nyelvek C++ Iterátorok

Programozás. (GKxB_INTM021) Dr. Hatwágner F. Miklós április 4. Széchenyi István Egyetem, Gy r

Adatszerkezetek 2. Dr. Iványi Péter

Struktúra nélküli adatszerkezetek

end function Az A vektorban elõforduló legnagyobb és legkisebb értékek indexeinek különbségét.. (1.5 pont) Ha üres a vektor, akkor 0-t..

Kupac adatszerkezet. A[i] bal fia A[2i] A[i] jobb fia A[2i + 1]

Tuesday, March 6, 12. Hasító táblázatok

Adatszerkezetek Tömb, sor, verem. Dr. Iványi Péter

Tömbök kezelése. Példa: Vonalkód ellenőrzőjegyének kiszámítása

6. előadás. Kiegyensúlyozottság, AVL-fa, piros-fekete fa. Adatszerkezetek és algoritmusok előadás március 6.

Adatbázisrendszerek I. Fájlszintű adattárolás C-ben

Szövegek C++ -ban, a string osztály

Átírás:

8. előadás Ismétlés Dinamikus adatszerkezetek: listák (egyszeresen vagy többszörösen láncolt), fák. Kétfelé ágazó fa: bináris fa Dinamikus adatszerkezetek - önhivatkozó adatstruktúrák: adatok és reájuk mutatni képes pointerek egy egységbe foglalva. Az ezek definiálására alkalmas adatszerkezet a C-ben a struktúra (lásd: Pascal RECORD), a struct A strukturák definiálásanak általános formai szabályait az alábbi ábra szerinti szintaktikai diagram adja meg: Például számokból álló, egyszeresen láncolt lista felépítéséhez az alábbi struktúra definíciót használhatjuk: struct szl { int szam; struct szl *kovetkezo; /* típuscímke segítségével hivatkozunk a struktúránkra */ elsosz, *elso, *futo; Ennek segítségével oldjuk meg a következő feladatot: Előre ismeretlen mennyiségű nem zérus értékű egész számot kell a memóriában eltárolnunk; a számokat folyamatosan olvassuk addig, amíg egy nulla nem érkezik. A megoldáshoz vezető gondolatmenetünk a következő: statikus tömbbel nem oldható meg a feladat, mert elképzelhető, hogy a tömb definiált méreténél több szám érkezhet, a többletet biztosan nem tudjuk tárolni. Szóba jöhet a dinamikus allokálású tömb is, de ehhez is előre ismerni kellene a tárolandó számok számát, hogy végre tudjuk hajtani a memóriaallokációt. Alapötlet: minden egyes adattal együtt hozzunk létre egy mutatót is, amin keresztül elérhetjük az esetleg következő, újabb adatot - tehát dinamikusan hozzunk létre azonos számú adattároló helyet is és pointert is és az egészet szervezzük egy láncolt listába. Az utolsó listaelem pointere szokás szerint NULL értékű legyen. A kitűzött feladat megoldásához a fenti szl struktúrát (számok listája) fogjuk alkalmazni, a fent definiált változókkal. A feladatot az alábbi kódrészletteol oldjuk meg: struct szl elsosz, *eleje, *futo, *p; int n; elsosz.szam = 0; /* elsosz struktúra szam adatmezőjét választjuk ki a. operátorral */ elsosz.kovetkezo = NULL /* nincs következő elem, ezért kovetkezo mező értéke NULL */ eleje = futo = &elsosz; /* elsosz statikus struktúra az első számot tárolja, ez lesz a lista eleje */ /* do - while ciklussal 0-ig olvasunk, láncba fűzzük a beolvasott számokat */ do { scanf("%d",&n); if (n) { p = (struct szl*)(malloc(sizeof(struct szl))); if (p!= NULL) /* sikeres memóriafoglalás a lánc egy új elemének */ { (*p).kovetkezo = NULL; 1 / 9 2012-10-17 22:24

(*p).szam = 0; (*futo).kovetkezo = p; (*futo).szam = n; futo = p; /* futo-t átállítjuk az új listaelemre */ while(n); Dinamikus adatszerkezet kezelésénél gyakori fordulat, hogy az adott listaelemet vagy fa csomópontot reprezentáló, dinamikusan allokált struktúrára csak egy pointer mutat rá, a struktúra mezőit ezen keresztül érjük el. Ehhez inidrektáljuk a pointert, majd az eredményül kapott struktúra típusú kifejezésre alkalmazva a mezőkiválasztó operátort férünk hozzá a kívánt mezőhoz. Ezt lerövidítendő, használhatjuk a -> struktúra-pointer mezőkiválasztó operátort: a (*struktúramutató).struktúramező kifejezéssl teljesen ekvivalens a struktúramutató->struktúramező kifejezés. Ezt felhasználva tekintsük a listában tárolt számok kiírását végző kódrészletet: Fésűs adatszerkezet futo = eleje; while (futo!= NULL) { printf("%d ",futo->szam); futo = futo->kovetkezo; Az eddigieknél összetetteb adatszerkezeteket is létrehozhatunk dinamikus adatszerkezetek formájában. A (lineáris) láncolt lista tulajdonképpen az egydimenziós tömbökre emlékeztet azzal a különbséggel, hogy a listaelemekhez csak szigorúan sorrendben (szekvenciálisan), a lánc mentén végighaladva fértünk hozzá. Akkor alakítottunk ki láncolt listát, ha ismeretlen számú adat gyors memórában tárolására volt szükségünk. Ez kiterjeszthető "két dimenzóra" is. Ekkor egy újabb belső szerkezetű láncot hozunk létre, amely listaszerűen pusztán az eddigi listáink kezdőcímeit tartalmazza. Ha ábrázoljuk egy ilyen szervezésű adatszerkezet sémáját, akkor egy fésűre emlékeztető rajzot kapunk, ezért az ilyen adatszerkezeteket fésűs adatszerkezeteknek nevezzük. Ezt szemlélteti az alábbi ábra: Ehhez egy típust (struktúrát) kell definiálnunk a fésű fogai számára, ahol a tényleges adatokat tároljuk és egy másik típust (struktúrát) kell definiálnunk a fésű "nyele" számára. Természetesen a "nyél" lista elemeiben is tárolhatunk adatokat, tipikusan a fogakat alkotó listák egyes globális jellemzőt. Példa: a fogakban egy egyetemi tankörbe beosztott hallgatók adatait tároljuk (egy lista - egy tankör alapon), míg a fésű nyele egy évfolyamot 2 / 9 2012-10-17 22:24

reprezentálhat, ahol az évfolyamot tankörökre osztottuk. Tankörönként tárolhatjuk pl. a tankörszintű tanulmányi átlagot, stb. Típusdefiniálás A C nyelv használata során sok egyszerűsítésre ad módot az, hogy pl. struktúrák esetében nem kell mindig a struct típuscímke fordulattal élnünk, ha valahogy elérjük azt, hogy egy struktúrát (vagy akármilyen más adattípust) a fordító pontosan olyan módon kezeljen, mint az előre definiált adattípusokat. Ehhez az kell, hogy egy közöljük a fordítóval azt, hogy egy adatszerkezet (mondjuk egy tömb vagy egy struct) leírása egy új adattípus definíciójaként tekintendő. Ezt a typedef kulcsszó segítségével tehetjük meg, az alábbi szintaktikai séma szerint: Rövid példaként egy olyan típus definícióját adjuk meg, amivel egy bináris fát lehet reprezentálni: typedef struct bf { char ch; struct bf *ti, *ta; btree, *pbtree; Ebben a példában btree egy struktúra típus, pbtree pedig egy struktúrára mutatni képes pointer típus azonosítója. Hogy lesz ebből bináris fa? Úgy, hogy úgy pointerezzük egymáshoz a memóriában dinamikusan létrehozott adatokat, hogy azok egy fát alkossanak. A fenti struktúra típus-definícióban szereplő két mutatómezővel akár egy kétirányú láncolt listát is felépíthetnénk. Az, hogy milyen típus azonosítókat és milyen struktúra mező azonosítókat használunk, tehát semmit sem jelent - csak a kód emberi olvasó általi érthetőségét segíti elő. Az alábbi ábra azt szemlélteti, hogy egy két pointermezőt tartalmaző önhivatkozó struktúrával akár ilyen, akár olyan dinamikus adatszerkezetet is felépíthetünk: Felmerülhet a kérdés, hogy mire használhatjuk a fákat. Az előző előadáson pl. rendezésre/keresésre használtuk - ezek voltak a rendező, ill. kereső fák. De használhatjuk pl. dekódolásra is. Ehhez tekintsük az alábbi fát: 3 / 9 2012-10-17 22:24

Ezen az ábrán - összhangban a btree típusdefiníciójával - az egyik irányba mutató pointert ti-vel, a másikba mutatót ta-val jelöltük. Nézzük, hogy juthatunk el a fa gyökeréből pl. az S betűhöz: ti-ti-ti utat kell bejárjuk. Az O-hoz pedig a ta-ta-ta utat. Ha megint az S-et szeretnénk elérni, az út a gyökérből megint csak ti-ti-ti. Talán már mindenki fel is ismerte az SOS vészjel Morsekódsorozatát. Ez a fa tehát egy Morse-dekódoló fa (ugyan a számjegyek kódjai hiányoznak belőle). Ezt felhasználva können írható egy Morse-dekódoló program. Ennek lényegi részét láthatjuk alább: pbtree morse_root, futo; char c, betu; morse_root =... /* valahogy a fenti tartalommal kitöltve létrehozzuk a dekódoló fát */... /*. és - karakterek kódolják a betüket, space határolja az egyes jelsorozatokat */ futo = morse_root; while (' '!= (c = getchar())) { switch(c) { case '.': futo = futo->ti; break; case '-': futo = futo->ta; break; betu = futo->ch; futo = morse_root; /* kezdjük előlről a következő kóddal */... Az alábbi ábra egy bináris keresőfát szemléltet. Ebben pl. egy telefonkönyv adatait tároljuk és a fa az előfizetők családi neve mint kulcs szerint rendezett. 4 / 9 2012-10-17 22:24

Dinamikus adatszerkezetek kezelése Láncolt listák jellegzetes műveleteit - új elem beszúrása, elem törlése - szemléltetik az alábbi ábrák: 5 / 9 2012-10-17 22:24

6 / 9 2012-10-17 22:24

Elem törlésénél fontos a free függvény meghívása - ez jelenti a tényleges, fizikai törlést és az allokált memóriaterület visszaadását az operációs rendszernek. Ne feledjük ezután a kérdéses pointer értékét NULL-lá tenni, jelezve, hogy az most már nem mutat sehová. Fenti példánk szerint tehát: torlendo = NULL; Példa a törlésre: typedef struct l { valami adat; struct l *kovetkezo; lista_t, *lista_poi;... lista_poi torles(lista_poi els, torl) { if (torl == els) elso = torl->kovetkezo; else els->kovetkezo = torl->kovetkezo; free(torl); return els;... elso = torles(elso, torlendo); torlendo = NULL; Figyelem: torlendo-t a torles függvényen kívül tettük NULL-lá - a függvényhívás mechanizmusának tárgyalásakor ennek az okát tisztázzuk. 7 / 9 2012-10-17 22:24

Fák kezelése: Keresés: 1. 2. 3. 4. Indulás a gyökérből Ha a kulcs egyezik, megvan az elem Ha kisebb, továbblépés a baloldali részfába, ha lehet; ha nagyobb, továbblépés jobbra, ha lehet. Ha már nem lehet a fában a rendezettség szerinti irányba továbblépni, az elem nincs benne a fában. Ha szükséges, az utolsóként bejárt csomópont megfelelő ágára felfűzhető - ezzel a keresett adatot fel is vettük a fába. Új elem beiktatása: 1. 2. 3. Üres a fa? Ha igen, új elemként felvesszük; ez lesz a gyökér. Ha nem üres a fa, az elem helyét meg kell keresni - lásd fent. Ha megtaláltuk az elemet a fában, nem kell tenni semmit, ha NULL-ba ütköztünk, akkor arra az ágra felfűzzük.így a fa automatikusan rendezetten épül. Törlés - nem triviális: Utód nélküli levél: nincs gond, a foglalt memóriát felszabadítjuk, a reá mutató pointert-t NULL-lá tesszük. 1 utóda van: a törlendő elemre mutató pointer értéke felülírandó a törlendő elem egyetlen utódára mutató értékkel, majd a foglalt memóriát felszabadítjuk. A törlés logikai részét szemlélteti az alábbi ábra: 2 utóda van: A törlés után a rendezettségnek fenn kell maradnia. A törölt elem helyére kerülő elemnek a törölt elem minden baloldali utódánál nagyobb kulcsúnak, minden jobboldali utódánál kisebb kulcsúnak kell lennie.lépések: 1. 2. Baloldali részfa legjobboldalibb elemének megkeresése. Ezt a törlendő elembe mozgatjuk át úgy, hogy a jobboldali mutatója a törlendő elem jobboldali eredeti részfájára mutasson, baloldali mutatója pedig a törlendő elem megmaradó baloldali részfájára mutasson. 8 / 9 2012-10-17 22:24

Fa teljes bejárása: typedef struct bf { valami adat; struct bf *bal, *jobb; bifa, *pbifa; void fabejaro(pbifa aktualis_csp) { if (aktualis_csp->bal!= NULL) fabejaro(aktualis_csp->bal); if (aktualis_csp->jobb!= NULL) fabejaro(aktualis_csp->jobb); aktualis_csp->adat feldolgozása Megjegyzés: az aktuális csomópontban tárolt adat feldolgozása akár a bal/jobb részfák bejárása előtt, akár a részfák bejárása után is megtörténhet, attol függően, hogy éppen mi az algoritmikus igény. 9 / 9 2012-10-17 22:24