Algoritmusok és adatszerkezetek

Slides:



Advertisements
Hasonló előadás
Programozási feladatok
Advertisements

Definíciók: Algoritmus: bármely véges sok lépéssel leírható tevékenység. Olyan pontos előírás, amely megmondja, hogy egy adott típushoz tartozó feladat.
Összefoglalás Hardver,szoftver,perifériák Memóriák fajtái
Algoritmusok.
Adatelemzés számítógéppel
 Megfigyelhető, hogy amikor több elem közötti összehasonlítás történik, akkor szükség van egyszerre több értékre is, főleg akkor, ha ezek az értékek jóval.
Összefoglalás 1. Pascal program szerkezete 2. Pascal típusai
Matematika és Tánc Felkészítő tanár: Komáromi Annamária
Algoritmus és programozás
Algoritmus Az algoritmus problémamegoldásra szolgáló elemi lépések olyan sorozata, amely: véges – azaz véges számú lépés után befejeződik, és eredményt.
Programozási alapismeretek 10. előadás
Programozás alapjai.
C A C nyelv utasításai.
C A C nyelv utasításai. Ismétlés Utasítások csoportosítása.
Egydimenziós tömbök. Deklarálás: var valtozónév:array[kezdőérték..végsőérték]of típus; type típusnév = array [kezdőérték..végsőérték] of típus; var valtozónév:
Készítette: Pető László
Nat Pedellus Informatika 8. osztály óra.
Java programozási nyelv 2. rész – Vezérlő szerkezetek
C++ Alapok, első óra Elemi típusok Vezérlési szerkezetek
Programozás I. Ciklusok
Vizuális és web programozás II.
Programozás Az adatokról C# -ban.
C nyelv utasításai.
A Pascal programozási nyelv alapjai
Ismétlés A pascal program szerkezete: program programnev; Programfej
Ismétlés.
Ciklusok: 3. Hátultesztelő ciklus
A Pascal programozási nyelv alapjai
ALGORITMUSOK.
Tömbök és programozási tételek
Algoritmusok és készítésük
Programozási nyelvek, Pascal
Ciklusok (iterációk).
Összetett adattípusok
Adatszerkezetek és algoritmusok
Algoritmusok.
Turbo Pascal Indítás: C:\LANGS\Turbo Pascal Turbo Pascal.
Algoritmus szerkezetek
Nevezetes algoritmusok
Java programozási nyelv Vezérlési szerkezetek
Algoritmusok.
Objektum orientált programozás
Az algoritmuskészítés alapjai
Feladatok (értékadás)
Programozás, programtervezés
Török Katalin és Marosi Nóra 11/c. Pascal: Az es években megjelent magas szintű programozási nyelv, közel áll az emberi gondolkodáshoz. Nevét.
Mintapélda Készítsünk programot, amely beolvas egy egész számot, és eldönti arról, hogy prímszám-e. Készítsünk programot, amely beolvas egy egész számot,
Nat Pedellus Free Pascal Elágazások..
Algoritmizálás és programozás tanítása Balogh Zoltán PTE-TTK IÁTT Az algoritmuskészítés.
Összeállította: Sashalmi Tibor
Free pascal feladatok
Algoritmizálás, adatmodellezés
Programozási alapismeretek 10. előadás. ELTE Szlávi-Zsakó: Programozási alapismeretek 10.2/  Kiválogatás + összegzés.
Kiterjesztések szemantikája: Szemantikai tartomány : Adatoknak, vagy értékeknek egy nem üres halmazát szemantikai tartománynak nevezzük. Jelölése: D. Egy.
Adatszerkezetek és algoritmusok 2006/ Algoritmus Az algoritmus szó eredete a középkori arab matematikáig nyúlik vissza, egy a i.sz. IX. században.
Excel programozás (makró)
UNIVERSITY OF SZEGED D epartment of Software Engineering UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás I. 3. gyakorlat.
C++2. Ciklusok elöltesztelő (for, while) A ciklusmag feldolgozása előtt történik a vizsgálat  lehet, hogy egyszer sem fut le. A soronkövetkező iteráció.
Programtervezés, programozás I. 2.5 tömbök,stringek
Adatszerkezetek és algoritmusok 2008/ Algoritmus Az algoritmus szó eredete a középkori arab matematikáig nyúlik vissza, egy a i.sz. IX. században.
TÁMOP /1-2F Informatikai gyakorlatok 11. évfolyam Alapvető programozási tételek megvalósítása Czigléczky Gábor 2009.
Algoritmus Algoritmus Az algoritmus szó eredete a középkori arab matematikáig nyúlik vissza, egy a i.sz. IX. században élt perzsa tudós nevének pontatlan.
Programozási alapok.
Nevezetes algoritmusok
Tömbök és programozási tételek
Algoritmizálás.
Bevezetés a programozásba Algoritmikus gondolkodás
Informatikai gyakorlatok 11. évfolyam
Informatikai gyakorlatok 11. évfolyam
Algoritmus készítés.
Előadás másolata:

Algoritmusok és adatszerkezetek Előadó: Dr. Nagy Mihály PHD, föiskolai tanár Algoritmusok és adatszerkezetek 2007/2008

1. Algoritmus Az algoritmus szó eredete a középkori arab matematikáig nyúlik vissza, egy a i.sz. IX. században élt perzsa tudós nevének pontatlan fordítása. Az algoritmus problémamegoldásra szolgáló elemi lépések olyan sorozata, amely: véges – azaz véges számú lépés után befejeződik, és eredményt szolgáltat; egyértelmű – a lépések sorozatát úgy határozzuk meg, hogy bármely végrehajtott lépés után egyértelműen adódik a következő; determinisztikus – ugyanazon kiindulási adatokra tetszőleges számú végrehajtás esetén ugyanazt az eredményt szolgáltatja; teljes – nemcsak egy konkrét esetre alkalmazható, hanem az összes azonos jellegű feladatra.

Szemléltetése Az algoritmusok tervezésére, szemléltetésé-re sokféle eszköz létezik, pl. folyamatábra: az algoritmus szerkezetét, a lépések sorrendjét teszi áttekinthetővé; leíró nyelv (mondatszerű leírás): az így meg-fogalmazott algoritmus közvetlenül átírható egy általános célú programozási nyelvre.

A folyamatábra szimbólumai az algoritmus kezdete Start adat be- és kivitel Be: változó Ki: kifejezés változó:=kifejezés értékadás Feltétel kétirányú elágazás (döntés) a lépések sorrendje az algoritmus vége Stop

Vezérlési szerkezetek A folyamatábrák készítése során a lépések sor-rendjét vezérlő folyamatvonal szinte tetszőleges helyre irányítható. Így olyan bonyolult szerkezeteket kaphatunk, amelyeket nagyon körülményes kódolni bármely programozási nyelvre. A hatékony programíráshoz szükségessé vált kevés számú, áttekinthető vezérlési szerkezet definiálása, melyek felhasználásával minden algoritmus megvalósítható.

Vezérlési szerkezetek Az 1960-as években bebizonyították (Dijkstra, strukturált programozás), hogy bármely algorit-mus leírható szekvencia, szelekció és iteráció segítségével. szekvencia: utasítások egymás utáni végrehajtási sorrendje, külön utasítást nem használunk a jelölé-sére; szelekció: egy feltétel igaz vagy hamis voltától függ, hogy bizonyos utasítások végrehajtódnak-e vagy sem; iteráció: lehetővé teszi meghatározott utasítások tet-szőleges számú ismételt végrehajtását.

Az általunk használt leírónyelv szintaxisa Változódeklarálás: változó változónév1, változónév2...: típus pl: változó Darabszám: egész változó Összeg, Átlag: valós Értékadó utasítás: változó:=kifejezés pl: Átlag:=Összeg/Darabszám

Beolvasó és kiíró utasítások be: vált1, vált2... ki: kif1, kif2... pl: be: Szám ki: Szám*Szám

Szelekciós (feltételes) utasítások ha feltétel akkor utasítás... hvége ha feltétel akkor utasítás... különben utasítás... hvége pl: ha a>b akkor c:=a különben c:=b hvége

Többszörös elágazás elágazás amikor feltétel1: utasítás… amikor feltétel2: utasítás… ... különben utasítás evége

Iterációs (ciklus) utasítások 1. elöltesztelő feltételes ciklus (while) amíg feltétel ismétel utasítás... avége pl: be: R amíg R<>0 ismétel ki: R*R*pi be: R avége

Iterációs (ciklus) utasítások 2. elöltesztelő előírt lépésszámú (léptető, növekményes) ciklus (for) ciklus cv:=ké..vé lépésköz: lk ismétel utasítás... cvége A használt rövidítések: ciklusváltozó, kezdőérték, végérték, lépésköz (lépésköz: 1 elhagyható). pl: ciklus I:=1..100 ismétel ki: I*I cvége

Iterációs (ciklus) utasítások 3. hátultesztelő feltételes ciklus ismétel utasítás... ivége feltétel esetén pl: ismétel be: Jegy ivége (Jegy>=1) és (Jegy<=5) esetén

2. Egyszerű, ciklikus feldolgozást igénylő algoritmusok Néhány gyakran használt alapalgoritmus általános sémája

Adatok feldolgozása végjelig Nem ismerjük az iterációk számát, ciklus végrehajtása attól függ, hogy van-e még feldolgozandó adat. Az adatfolyam végét egy végjel jelzi. be: Adat amíg Adat<>Végjel ismétel Az adat feldolgozása be: Adat avége Mivel a végjelet nem kell feldolgoznunk, ezért célszerű az adat beolvasását a ciklusmag végén elvégeznünk, így a vezérlő feltétel következő kiértékelésekor befejeződik a ciklus. Ez első adatot a ciklus előtt olvassuk be, ezt előolvasásnak nevezzük. Az algoritmus akkor is jól működik, ha nincs adat.

Adatok feldolgozása végjelig Példa: Olvassuk be körök sugarait nulla végjelig (addig, amíg nullát nem ütünk), majd írjuk ki a kerületét és a terü-letét! Leíró nyelv: változó r,k,t:valós be: r amíg r<>0 ismétel k:=2*r*pi t:=r*r*pi ki: k ki: t be: r avége

Pascal: program Korok; uses Crt; var R, K, T: real; begin ClrScr; Write('Sugár: '); ReadLn(R); while R<>0 do K:=2*R*Pi; T:=R*R*Pi; WriteLn('A kerülete:', K:8:2); WriteLn('A területe:', T:8:2); WriteLn; end; end.

C #include<stdio.h> #include<math.h> main(){ float r,t,k; printf("Sugár: "); scanf("%f",&r); while(r){ k=2*r*M_PI; t=r*r*3.14; printf("A kerülete: %f\n", k); printf("A területe: %f\n", t); printf("\nSugár: "); }

Java: import extra.*; public class Korok{ public static void main(String[]args){ double r,t,k; r=Console.readDouble("Sugár: "); while(r!=0){ k=2*r*Math.PI; t=r*r*Math.PI; System.out.println("A kerülete: "+k); System.out.println("A területe: "+t); }

Megszámlálás Egy sorozat, adatfolyam valamilyen adott tulajdonságú elemeinek a számát akarjuk meghatározni. Felveszünk egy számláló változót, melynek az értékét növeljük, ha az elem kívánt tulajdonságú. A számlálót természetesen le kell nulláznunk. Ha előre ismerjük az elemek számát, akkor for ciklust használhatunk, ha nem akkor az előző pontban megismert végjelig történő feldolgozást alkalmazzuk.

Megszámlálás – előre ismert elemszám ciklus i:=1..N ismétel Hozzáférés az i. elemhez ha az i. elem az adott tulajdonságú akkor Számláló:=Számláló+1 hvége cvége

Megszámlálás – előre nem ismert elemszám Hozzáférés az 1. elemhez amíg Elem<>Végjel ismétel ha az Elem az adott tulajdonságú akkor Számláló:=Számláló+1 hvége Hozzáférés a következő elemhez avége

Példa1: Olvassunk be 10 számot, és írjuk ki, hogy mennyi hárommal osztható volt közöttük! program Oszthato1; uses Crt; var A, Szamlalo, i: integer; begin ClrScr; Szamlalo:=0; for i:=1 to 10 do Write('Kérem az ', i, '. számot: '); ReadLn(A); if A mod 3 = 0 then Inc(Szamlalo); end; Writeln(Szamlalo, ' hárommal osztható volt.'); end.

Példa2: Olvassunk be számokat nulla végjelig, és írjuk ki, hogy mennyi hárommal osztható volt közöttük! program Oszthato2; uses Crt; var A, Szamlalo: integer; begin ClrScr; Szamlalo:=0; Write('Kérem a számot: '); ReadLn(A); while A<>0 do if A mod 3 = 0 then Inc(Szamlalo); end; Writeln(Szamlalo, ' hárommal osztható volt.'); end.

Összegzés Egy sorozat elemeit valamilyen módon gyűjteni kell, összegezni, esetleg a szorzatukat képezni. Ismert elemszám esetén az algoritmus:   Összeg:=0 ciklus i:=1..N ismétel Hozzáférés az i. elemhez Összeg:=Összeg+i. elem cvége

Összegzés Ismeretlen elemszám esetén az algoritmus: Összeg:=0   Összeg:=0 Hozzáférés az első elemhez amíg Elem <> Végjel ismétel Összeg:=Összeg+ Elem Hozzáférés a következő elemhez avége

Példa: 0 végjelig olvassunk be számokat, és számoljuk ki a párosak összegét! Itt egy picit bonyolítottuk az algoritmust, hiszen nem minden adatot kell össze-geznünk. program Oszegzes; uses Crt; var Osszeg, A: integer; begin ClrScr; Osszeg:=0; Write('Kérem a számot: '); ReadLn(A); while A<>0 do if A mod 2 = 0 then Osszeg:=Osszeg+A; end; Writeln('A párosak összege: ', Osszeg); end.

Átlagszámítás Az átlagszámítás során egy megszámlálást és egy összegzést kell párhuzamosan végeznünk.

Példa: 0 végjelig olvassunk be számokat, és számoljuk ki az átlagukat! program Atlag_Szamitas; uses Crt; var Osszeg, A, Szamlalo: integer; Atlag: real; begin ClrScr; Osszeg:=0; Szamlalo:=0; Write('Kérem a számot: '); ReadLn(A); while A<>0 do Osszeg:=Osszeg+A; Inc(Szamlalo); end; Atlag:=Osszeg/Szamlalo; Writeln('A számok átlaga: ', Atlag:8:2); end.

Minimum- és maximum- kiválasztás Egy sorozat legkisebb, illetve legnagyobb elemét kell kiválasztanunk. Az algoritmus lényege, hogy használunk egy Min, illetve Max változót, amely a már beolvasott elemek minimumát, illetve maximumát tartal-mazza. Ha az éppen vizsgált adat kisebb, mint a minimum, akkor ez lesz a minimum új értéke. Hasonlóan járunk el a maximumnál. A Min és Max kezdőértékének az első adatot választjuk.

Ismert elemszám esetén az algoritmus: Hozzáférés az első elemhez Min:=1. elem Max:=1. elem ciklus i:=2..N ismétel Hozzáférés az i. elemhez ha az i. elem < Min akkor Min:=i. elem különben ha az i. elem > Max akkor Max:=i. elem hvége cvége

Ismeretlen elemszám esetén az algoritmus: Hozzáférés az első elemhez Min:=1. elem Max:=1. elem amíg Elem<>Végjel ismétel ha Elem<Min akkor Min:=Elem különben ha Elem>Max akkor Max:=Elem hvége Hozzáférés a következő elemhez avége

Példa: 0 végjelig olvassunk be számokat, és írjuk ki a legkisebbet és a legna-gyobbat! program MinMax; uses Crt; var A, Min, Max: integer; begin ClrScr; Write('Kérem a számot: '); ReadLn(A); Min:=A; Max:=A; while A<>0 do if A<Min then Min:=A else if A>Max then end; WriteLn('A legkisebb szám: ', Min); WriteLn('A legnagyobb szám: ', Max); end.

3. Típusok, adatszerkezetek

Változó Névvel ellátott tárolóhely a számítógép memóriá-jában. A változó értéke ezen tárolóhely pillanatnyi értéke. A változó komponensei: név típus tárbeli kezdőcím érték

Típus Egy típus meghatározza a tároló tartalmá-nak értelmezését. Egy nyelv egy típusának jellemzése: felvehető értékek halmaza, adatábrázolás konstansai végezhető műveleteket rendelkezésre álló eljárások, függvények

Java – double típus Felvehető értékek halmaza, adatábrázolás dupla pontosságú 64-bit formátumú IEEE 754 értékek Konstansai: pl. 1e1 2. .3 0.0 3.14 1e-9d 1.6E137 Műveletek összehasonlító (logikai eredmény) numerikus (lebegőpontos eredmény) string konkatenálás (+, string eredmény) feltételes operátor, típus konvertáló operátor Függvények, eljárások Milyen osztályok támogatják a lebegőpontos számításokat (pl. Math.pow, Math.sin, Math.round …)

Típusok csoportosítása Elemi típusok: az algoritmus szempontjából nincs szerkezetük, nem tudjuk az egyes részeit külön kezelni egész valós karakter logikai mutató

Típusok csoportosítása Összetett típusok: elemi vagy összetett típusokat tartalmaznak valamilyen szerke-zeti összefüggés szerint (adatszerkezetek) tömb karakterlánc rekord állomány „Ha valaki megértette már a változók használatát a programozásban, akkor megértette a programozás lényegét” (E .W. Dijkstra)

4. Tömb A legalapvetőbb, leggyakrabban használt adatszerkezet. Olyan homogén adatszerkezet, melynek elemeit a sokaságon belül elfoglalt helyük azonosítja. Tehát: elemei azonos típusúak, az elemeket nem névvel, hanem a tömbön belüli helyükkel, az indexükkel azonosítjuk.

Tömb deklarálása Deklaráláskor meg kell adnunk a tömb: nevét elemeinek típusát indextartományát dimenzióját. Egy dimenziós tömb: vektor, sorozat. Két dimenziós tömb: mátrix, táblázat.

Tömb deklarálása Leírónyelv változó tömbnév: tömb[alsóhatár..felsőhatár] elemtípus változó tömbnév: tömb[ah1..fh1, ah2..fh2] elemtípus   A tömb elemeinek száma: elemszám = felsőhatár – alsóhatár + 1 elemszám = (fh1 – ah1 + 1) * (fh2 – ah2 + 1)

Tömbök feldolgozása A tömbök feldolgozása gyakran jelenti ugyanazon műveletek ismétlését az egyes elemekre, ez pedig tipikusan valamilyen ciklus alkalmazásához vezet. Különösen a léptető (for) ciklus kötődik szorosan a tömbökhöz, mert a ciklusváltozó jól használható a tömbelemek egymás utáni megcímzésére.

Tömbök feldolgozása ciklus cv:=alsóhatár..felsőhatár ismétel tömbnév[cv] ... cvége   ciklus cv1:=alsóhatár1..felsőhatár1 ismétel ciklus cv2:=alsóhatár2..felsőhatár2 ismétel tömbnév[cv1,cv2] ...

Tömbök tárolása Sorfolytonosan: ez lehetővé teszi, hogy bármely elem helyét az indexek ismeretében kiszámíthassuk, s így közvetlenül elérhes-sük őket. A tömb méretétől függetlenül bár-melyik elemét ugyanannyi idő alatt érhetjük el.

4.1. Vektorkezelő elemi algoritmusok

Az elemek egymás után történő feldolgozása ciklus i:=1..N ismétel A[i] feldolgozása cvége   Példa: Töltsünk fel egy tömböt emberek életkorával, majd írassuk ki! const Max=10; var Evek:array[1..Max]of byte; I:byte; begin for I:=1 to Max do readln(Evek[I]); writeln; for I:=1 to Max do write(Evek[I]:4); end.

Megszámlálás, összegzés, átlagszámítás, min. és max. kiválasztás Lásd 2. fejezet, ismert elemszámú esetek, ahol a hozzáférés az i. elemhez triviális módon az indexeléssel történik. Például átlagszámítás:   Összeg:=0 ciklus i:=1..N ismétel Összeg:=Összeg+A[i] cvége Átlag:=Összeg/N

Gyűjtés Hasonló a számláláshoz, de itt a bejövő elemeket valamilyen tulajdonság, szempont szerint szelektáljuk. Számláló változó helyett egy gyűjtőtömböt használunk, melynek elemei a számlálók, amelyek egy-egy különböző tulajdon-ságnak felelnek meg.

Gyűjtés – általános algoritmus Ismeretlen elemszám: Gyűjtő tömb inicializálása (többnyire lenullázása) Hozzáférés az első elemhez amíg Elem <> Végjel ismétel Elem vizsgálata, Index képzése Gyűjtő[Index] módosítása (pl. inkrementálása) Hozzáférés a következő elemhez avége Ismert elemszám: Gyűjtő tömb inicializálása (többnyire lenullázása) ciklus i:=1..N ismétel Hozzáférés az i. elemhez Elem vizsgálata, Index képzése Gyűjtő[Index] módosítása (pl. inkrementálása) cvége

Gyűjtés – indexképzés Az Index képzése azt jelenti, hogy meg kell vizsgálnunk, hogy az adott Elem milyen tulajdonságú, azaz melyik Gyűjtő tömb elemhez tartozik (melyik Gyűjtő tömb elemet kell növelni).

Gyűjtés – példák 1. Olvassunk be osztályzatokat 0 végjelig, és számoljuk meg, hogy hány ötös, négyes, hármas, kettes, illetve egyes volt közöttük. Itt az index képzése nagyon egyszerű, hiszen a vizsgált elem, azaz a jegy maga az index. 2. Számoljuk meg, hogy az életkorokat tartalma-zó tömbben hány 10 évnél fiatalabb, tizenéves, huszonéves, … ember adata van. Az indexet az adatból egy egyszerű matematikai művelettel kapjuk meg

1. program JegySzam; uses Crt; var Gyujto: array[1..5] of integer; Jegy, i: byte; begin ClrScr; {A gyűjtő tömb inicializálása} for i := 1 to 5 do Gyujto[i] := 0;   {Gyűjtés} Write('Osztályzat: '); ReadLn(Jegy); while Jegy <> 0 do Inc(Gyujto[Jegy]); end; {Kiírás} WriteLn; WriteLn(i, ': ',Gyujto[i],' db'); end.

2. const Max=10; var Evek:array[1..Max]of byte; Gyujto:array[0..12]of byte; i:byte; begin for i:=1 to Max do readln(Evek[i]);   for i:=0 to 12 do Gyujto[i]:=0; inc(Gyujto[Evek[i] div 10]); writeln; for i:=0 to 12 do writeln(i*10,' - ',(i+1)*10,': ',Gyujto[i]); end.

Programozási tételek A következő sorozat feldolgozó algoritmu-sokat programozási tételeknek is nevezik. A sorozatokat a példáinkban tömbök tárolják, bár az algoritmusok általánosak.

Másolás Egy bemenő sorozatból egy kimenő sorozatot készítünk, mégpedig úgy, hogy az eredmény-sorozat ugyanolyan elemszámú, mint a bemene-ti sorozat, és az eredménysorozat i. tagját a bemenő sorozat i. tagjából lehet meghatározni. A bemenő sorozatot tehát átmásoljuk úgy, hogy közben az elemeken esetleges átalakításokat végzünk.

Másolás – általános algoritmus algoritmus Másolás ciklus i:=1..NBemenő ismétel Bemenő sorozat i. eleméből Kimenő sor i. elemének előállítása cvége algoritmus vége Példa: A születési éveket tartalmazó tömbből hozzunk létre egy tömböt, mely az életkorokat tartalmazza.

algoritmus ÉletkorMásol; konstans Max=10; konstans FolyóÉv=2007; változó Évek, Szül:tömb[1..Max] egész; változó i: egész; ciklus i:=1..Max ismétel be: Szül[i]; cvége   Évek[i]:=FolyóÉv-Szül[i] ki: Szül[i],": ",Évek[i] algoritmus vége

program EletkorMasol; const Max=10; FolyoEv=2005; var Evek:array[1..Max]of byte; Szul:array[1..Max]of word; i:word; begin for i:=1 to Max do readln(Szul[i]);   Evek[i]:=FolyoEv-Szul[i]; writeln; writeln(Szul[i],': ',Evek[i]); end.

Kiválogatás Egy bemenő sorozatból egy kimenő sorozatot készítünk, úgy, hogy a bemenő sorozat elemei közt válogatunk. Az eredménysorozat rövidebb vagy ugyanakkora lesz, mint a bemenő sorozat. Ide tartozó feladat például: Töröljünk ki egy karakterláncból minden szóközt! Válogassuk ki a fizetések közül azokat, amelyek kisebbek, mint 150000!

Kiválogatás – általános algoritmus algoritmus kiválogatás NKimenő:=0 ciklus i:=1..NBemenő ismétel ha Bemenő[i] a megadott tulajdonságú akkor NKimenő:=NKimenő+1 Kimenő[NKimenő]:=Bemenő[i] hvége cvége algoritmus vége Példa: Válogassuk ki egy születési éveket tartalmazó sorozatból a hatvan évesnél idősebb személyek születési éveit!

algoritmus IdősekKiválogatása konstans Max=10; konstans FolyóÉv=2007; változó Szül, Idősek: tömb[1..Max] egész; változó i, IdősekSzáma: egész; ki: "Írjon be ",Max," darab születési évet!" ciklus i:=1..Max ismétel be: Szül[i] cvége IdősekSzáma:=0; ha FolyóÉv-Szül[i]>60 akkor IdősekSzáma:=IdősekSzáma+1 Idősek[IdősekSzáma]:=Szül[i]; hvége ki: "Az idősek:" ciklus i:=1.. IdősekSzáma ismétel ki: Idősek[i] algoritmus vége

Program Kivalogatas; const Max=10; FolyoEv=2005; var Szul, Idosek: array[1..Max]of word; i, IdosekSzama: word; begin writeln(’Írjon be ’,Max,’ darab születési évet!’); for i:=1 to Max do readln(Szul[i]); IdosekSzama:=0; if FolyoEv-Szul[i]>60 then inc(IdosekSzama); Idosek[IdosekSzama]:=Szul[i]; end; writeln(’Az idősek:’); for i:=1 to IdosekSzama do writeln(Idosek[i]); end.

Szétválogatás Egy bemenő sorozatból több kimenő sorozatot készítünk. Azok a feladatok tartoznak ide, amelyeknél a bejövő adatok minde-gyikére szükségünk van ugyan, de azokat valamilyen szempontból el kell különíteni, szét kell válogatni. A kimenő sorozatok elemszámainak összege megegyezik a bemenő sorozat elemszámával. A szétválogatást fel lehet fogni több egymás utáni kiválogatásként is, ahol egyszer minden elemre sor kerül. Mindegyik eredménysorozatban ugyanannyi elemszámra kell fel-készülni, mint a bemenő sorozat elemszáma, hiszen szélsőséges esetben elképzelhető, hogy minden elem egyetlen kimenő sorozatba kerül át. Ide tartozó feladat például: A bejövő személyi számokat bontsuk ketté: férfiak, nők! Dolgozók bejövő adatrekordjait válogassuk szét foglalkozás szerint!

Szétválogatás – ált. algoritmus algoritmus szétválogatás NKimenő1:=0 NKimenő2:=0 ... ciklus i:=1..NBemenő ismétel elágazás amikor Bemenő[i] az 1. tulajdonságú: NKimenő1:=NKimenő1+1 Kimenő1[NKimenő1]:=Bemenő[i] amikor Bemenő[i] az 2. tulajdonságú: NKimenő2:=NKimenő2+1 Kimenő2[NKimenő2]:=Bemenő[i] különben evége cvége algoritmus vége

Példa: A bejövő születési éveket tartalmazó sorozatból készítsünk két sorozatot: egyikben legyenek a fiatalok, a másikban pedig az idősek. algoritmus KorSzétválogatás; konstans Max=10; konstans FolyóÉv=2007; változó Szül, Idősek, Fiatalok: tömb[1..Max] egész; változó i, IdősekSzáma, FiatalokSzáma: egész; ki: "Írjon be ",Max," darab születési évet!" ciklus i:=1..Max ismétel be: Szül[i] cvéve FiatalokSzáma:=0; IdősekSzáma:=0;

ha FolyóÉv-Szül[i]>60 akkor IdősekSzáma:= IdősekSzáma+1 ciklus i:=1..Max ismétel ha FolyóÉv-Szül[i]>60 akkor IdősekSzáma:= IdősekSzáma+1 Idősek[IdősekSzáma]:=Szül[i]; különben FiatalokSzáma:= FiatalokSzáma+1 Fiatalok[FiatalokSzáma]:=Szül[i]; hvége cvége ki: "Az idősek:" ciklus i:=1..IdősekSzáma ismétel ki: Idősek[i] ki: "A fiatalok:" ciklus i:=1.. FiatalokSzáma ismétel ki: Fiatalok[i] algoritmus vége

program Szetvalogatas; const Max=10; FolyoEv=2005; var Szul, Idosek, Fiatalok: array[1..Max]of word; i, IdosekSzama, FiatalokSzama: word; begin writeln('Írjon be ',Max,' darab születési évet!'); for i:=1 to Max do readln(Szul[i]); FiatalokSzama:=0; IdosekSzama:=0; if FolyoEv-Szul[i]>60 then inc(IdosekSzama); Idosek[IdosekSzama]:=Szul[i]; end else inc(FiatalokSzama); Fiatalok[FiatalokSzama]:=Szul[i]; end; writeln('Az idősek:'); for i:=1 to IdosekSzama do writeln(Idosek[i]); writeln('A fiatalok:');; for i:=1 to FiatalokSzama do writeln(Fiatalok[i]); end.

Közös rész meghatározása Az ilyen típusú feladatoknál két vagy több sorozatból készítünk egy sorozatot úgy, hogy az eredménysorozat-ban csak olyan elemek szerepelnek, melyek mindegyik sorozatban benne vannak. A sorozatok nem rendezettek, de feltételezzük, hogy egy elem csak egyszer szerepel a sorozatban. A sorozatok tulajdonképpen halmazok, ahol a bejövő sorozatok közös részét (metszetét) képezzük. Az eredménysorozat elemszáma kisebb vagy egyenlő, mint a legrövidebb bemenő sorozat elemszáma.

Közös rész meghatározása Ilyen feladat például: Szilveszteri bulit szervezünk. Mindenki felsorolja, milyen márkájú söröket szeret. Milyen söröket vegyünk, ha mindenkinek kedvezni akarunk? Az egyes tanórákon írt katalógusokból megállapítjuk, hogy mely hallgató voltak jelen minden alkalommal. Megoldás: végigmegyünk az első sorozaton, és minden elemhez végignézzük a második sorozatot, van-e benne ugyanolyan elem. Ha több bemenő sorozat van, akkor a többit is végignézzük. Csak akkor vesszük fel az elemet a kimenő sorozatba, ha az elemet mindegyik sorozatban megtaláltuk.

Az általános algoritmus: függvény Van(Sorozat, Elem, NSorozat): logikai i:=1 amíg (i<=NSorozat) és (Sorozat[i]<>Elem) ismétel i:=i+1 avége Van:=i<=NSorozat függvény vége algoritmus Közösrész NKimenő:=0 ciklus i:=1..NBemenő1 ismétel ha Van(Bemenő2, Bemenő1[i], NBemenő2) és Van(Bemenő3, Bemenő1[i], NBemenő3) és ... akkor NKimenő:=NKimenő+1 Kimenő[NKimenő]:=Bemenő1[i] hvége cvége algoritmus vége

algoritmus Szépokosak konstans SzépekSzáma=10 konstans OkosakSzáma=15 Példa: Egy csoportban valaki összeírja a szép embereket, aztán az okosakat. E két névsor alapján határozzuk meg a csoport szép és okos embereit! (A névsorok nem rendezettek.) algoritmus Szépokosak konstans SzépekSzáma=10 konstans OkosakSzáma=15 változó Szépek: tömb[1..SzépekSzáma] karakterlánc változó Okosak: tömb[1..OkosakSzáma] karakterlánc változó SzépekOkosak: tömb[1..SzépekSzáma] karakterlánc változó SzépekOkosakSzáma, I, J: egész ki: "Írja be a szépek neveit!" ciklus I:=1..SzépekSzáma ismétel be: Szépek[I] cvége ki: "Írja be az okosak neveit!" ciklus I:=1..OkosakSzáma ismétel be: Okosak[I]

SzépekOkosakSzáma:=0 ciklus I:=1..SzépekSzáma ismétel J:=1 amíg (J<=OkosakSzáma) és (Szépek[I]<>Okosak[J]) ismétel J:=J+1 avége ha J<=OkosakSzáma akkor SzépekOkosakSzáma:= SzépekOkosakSzáma+1 SzépekOkosak[SzépekOkosakSzáma]:= Szépek[I] hvége cvége ki: "A szép és okos emberek:" ciklus I:=1.. SzépekOkosakSzáma ismétel ki: SzépekOkosak[I] algoritmus vége

Egyesítés Ebben a feladatcsoportban is több bemenő sorozatból készítünk egy kimenő sorozatot. Itt azonban azokat az elemeket tesszük be az eredménysorozatba, melyek legalább az egyik bemenő sorozatban benne vannak. A sorozatok itt is felfoghatók halmazként, a bemenő sorozatok unióját képezzük. Az eredménysorozat elemeinek száma legfeljebb a bemenő sorozatok elemszámainak az összege.

Egyesítés Ilyen feladat például: Megoldás: Csapatunk egy hetes túrára indul. Minden tag felsorolja, hogy milyen ételeket tud elkészíteni. Állapítsuk meg, hogy a csapatunk mire képes Az egyes tanórákon írt katalógusokból megállapítjuk, hogy mely hallgató voltak jelen valamelyik alkalommal. Megoldás: Az első sorozatot átmásoljuk az eredménysorozatba. Ezután végignézzük a második sorozatot, és minden egyes elemre megállapítjuk, hogy már bent van-e az eredménysoro-zatban. Ha nincs, akkor betesszük. Ezt elvégezzük az összes bemenő sorozatra.

Az általános algoritmus: algoritmus Egyesítés ciklus I:=1..NBemenő1 ismétel Kimenő[I]:=Bemenő1[I] cvége NKimenő:=NBemenő1 ciklus I:=1..NBemenő2 ismétel J:=1 amíg (J<=NKimenő) és (Bemenő2[I]<>Kimenő[J]) ismétel J:=J+1 avége ha J>NKimenő akkor NKimenő:=NKimenő+1 Kimenő[NKimenő]:=Bemenő2[I] hvége ciklus I:=1..NBemenő3 ismétel ... algoritmus vége

Példa: Apa és anya felsorolják, hogy a következő hónapban mely estéjük szabad. Gyűjtsük össze azokat a napokat, amikor legalább az egyikük ráér, és így nem kell babysitter-t fogadni. algoritmus NapokEgyesítése változó ApaSzabad, AnyaSzabad, ValakiSzabad: tömb[1..31] egész változó NApa, NAnya, NValaki, I, J: egész ki: "Apa hány nap szabad: " be: NApa ki: "Adja meg a szabad napjai sorszámait: " ciklus I:=1..NApa ismétel be: ApaSzabad[I] cvége ki: "Anya hány nap szabad: " be: NAnya ciklus I:=1..NAnya ismétel be: AnyaSzabad[I]

ciklus I=1..NApa ismétel ValakiSzabad[I]:=ApaSzabad[I] cvége NValaki:=NApa ciklus I:=1..NAnya ismétel J:=1 amíg (J<=NValaki) és (AnyaSzabad[I]<> ValakiSzabad[J]) ismétel J:=J+1 avége ha J>NValaki akkor NValaki:=NValaki+1 ValakiSzabad[NValaki]:=AnyaSzabad[I] hvége ki: "Amikor valaki ráér:" ciklus I:=1..NValaki ismétel ki: ValakiSzabad[I] algoritmus vége

Összeválogatás Ennél a feladattípusnál több bemenő sorozatból egy kimenő sorozatot készítünk. A bemenő sorozatok itt rendezettek, melyeket egyszerre dolgozzuk meg úgy, hogy közben a benne lévő elemeket összeválogatjuk. Először hozzáférhetővé tesszük az összes sorozatból az első elemet. Amelyik a legkisebb azt feldolgozzuk (pl. áttesszük az új sorozatba). A feldolgozott elem helyére mindig teszünk egy újat ugyanabból a sorozatból. A rendezettség miatt a csoportok egyenlő elemei egyszerre lesznek elérhetőek. Egyes feladatoknál ezt figyelhetjük, és az egyforma elemeket tesszük át az új sorozatba. Minden sorozatot egyszerre olvasunk végig párhuzamosan, és a feldolgozás végére készen lesz az eredménysorozat.

Az összeválogatás durva algoritmusa Ráállás a bemenő sorozatok első elemeire amíg van elem mindegyik sorozatban ismétel Elemek összehasonlítása Amelyik elem kell, azt feldolgozzuk, pótoljuk avége

Összeválogatás – speciális esetek Összefuttatás: az összeválogatásnak az az esete, amikor minden elemet beteszünk egy eredménysorozatba, Összefésülés: ha a bemenő sorozatoknak nincs közös elemük

Összeválogatás A legnagyobb problémát az egyes sorozatok végeinek feldolgozása jelenti: Hogyan állapítjuk meg azt, hogy van-e még valamelyik sorozatban elem? Hogyan pótoljuk azt a sorozatot, amelyikben már nincs elem? Egy példán keresztül nézzük meg az egyes módszereket! Példa: Állítsuk elő két rendezett sorozat (A, B) „rende-zett unióját” (C)! Az egyes sorozatokban nincsenek egy-forma elemek, de közös elemük lehet.

1. algoritmus A két sorozatot párhuzamosan dolgozzuk fel, amíg van elem mindkét sorozatban. algoritmus RendezettUnió1 konstans N=... konstans M=... változó A: tömb[1..N] ElemTípus változó B: tömb[1..M] ElemTípus változó C: tömb[1.. változó K, I, J: egész K:=0; I:=1; J:=1; N+M] ElemTípus

amíg (I<=N) és (J<=M) ismétel K:=K+1 elágazás amikor A[I]<B[J]: C[K]:=A[I]; I:=I+1 amikor A[I]>B[J]: C[K]:=B[J]; J:=J+1 különben C[K]:=A[I]; I:=I+1; J:=J+1 evége avége amíg I<=N ismétel amíg J<=M ismétel algoritmus vége

2. algoritmus A bemenő sorozatok végére fizikailag egy-egy „ütközőt” helyezünk. Az ütköző egy olyan elem, amely értéke bármely, a feldolgozásban résztvevő elemnél nagyobb. A feldolgozás végét kétféleképpen figyelhetjük: van-e még elem valamelyik sorozatban, (RendezettUnió2_1) ütközőn állunk-e mindegyik sorozatban (RendezettUnió2_2). Amelyik adatsorban az ütközőn állunk, az természetesen már nem ad elemet a kimenő sorozatba.

algoritmus RendezettUnió2_1 konstans MAX=... konstans N=... konstans M=... változó A: tömb[1..N+1] ElemTípus változó B: tömb[1..M+1] ElemTípus változó C: tömb[1..N+M] ElemTípus változó I, J, K: egész K:=0; I:=1; J:=1; A[N+1]:=MAX; B[M+1]:=MAX; amíg (I<=N) vagy (J<=M) ismétel K:=K+1 elágazás amikor A[I]<B[J]: C[K]:=A[I]; I:=I+1 amikor A[I]>B[J]: C[K]:=B[J]; J:=J+1 különben C[K]:=A[I]; I:=I+1; J:=J+1 evége avége algoritmus vége

Módosítsuk az előző példát három bemenő sorozat esetére. Ha több sorozatunk van, nem egymáshoz hasonlítjuk a vizsgált ele-meket, hanem közülük a legkisebbhez. Célszerűbb az ütközőt, mint végjelet figyelnünk. Módosítsuk az előző példát három bemenő sorozat esetére. algoritmus RendezettUnió2_2 konstans MAX=..., N=..., M=..., P=... változó A: tömb[1..N+1] ElemTípus változó B: tömb[1..M+1] ElemTípus változó C: tömb[1..P+1] ElemTípus változó D: tömb[1..N+M+P] ElemTípus változó I, J, K, L: egész változó Min:ElemTípus függvény Minimum(Elem1, Elem2, Elem3):Elemtípus Min:=Elem1 ha Elem2<Min akkor Min:=Elem2 hvége ha Elem3<Min akkor Min:=Elem3 hvége Minimum:=Min függvény vége

L:=0; I:=1; J:=1; K:=1 A[N+1]:=MAX; B[M+1]:=MAX; C[P+1]:=MAX; Min:=Minimum(A[I], B[J], C[K]) amíg Min<Max ismétel L:=L+1 D[L]:=Min ha A[I]=Min akkor I:=I+1 hvége ha B[J]=Min akkor J:=J+1 ha C[K]=Min akkor K:=K+1 avége algoritmus vége

Ezen módszerrel válogassuk össze az egyforma elemeket („rendezett metszet”) algoritmus RendezettMetszet2_2 ... Min:=Minimum(A[I], B[J], C[K]) amíg Min<Max ismétel ha (A[I]=Min) és (B[J]=Min) és(C[K]=Min) akkor L:=L+1 D[L]:=Min hvége ha A[I]=Min akkor I:=I+1 ha B[J]=Min akkor J:=J+1 ha C[K]=Min akkor K:=K+1 avége algoritmus vége

3. algoritmus A bemenő sorozatok végére logikai ütkö-zőket helyezünk. Ez azt jelenti, hogy minden pótláskor fi-gyeljük, hogy elfogyott-e a sorozat, és ha igen, akkor az utolsó elem értékét „végte-lenre” állítjuk. A feldolgozásnak akkor van vége, ha min-degyik elem értéke végtelen.

algoritmus RendezettUnió3 konstans MAX=... konstans N=... konstans M=... változó A: tömb[1..N] ElemTípus változó B: tömb[1..M] ElemTípus változó C: tömb[1..N+M] ElemTípus változó K, I, J: egész változó Min: ElemTípus   eljárás ALéptet I:=I+1 ha I<=N akkor AElem:=A[I] különben AElem:=Max hvége eljárás vége eljárás BLéptet J=J+1 ha J<=M akkor BElem:=B[J] különben BElem:=Max hvége eljárás vége

függvény Minimum(Elem1, Elem2): ElemTípus ha Elem1<Elem2 akkor Minimum:=Elem1 különben Minimum:=Elem2 függvény vége   K:=0; I:=0; J:=0; ALéptet; BLéptet Min:=Minimum(AElem, BElem) amíg Min<Max ismétel K:=K+1 C[K]:=Min ha AElem=Min akkor ALéptet hvége ha BElem=Min akkor BLéptet avége algoritmus vége

4.2. Rendezések A rendezési feladatok általános problémája: adott egy n elemű sorozat, készítsük el ezeknek az elemeknek egy olyan permutációját, amelyre igaz, hogy a sorozat i. eleme kisebb (egyenlő) az i+1-ediktől. Ez a növekvő rendezés. Az ilyen algoritmusok értelemszerűen átalakíthatók csökkenő sorrendűvé.

A különböző rendezések leginkább a következő két művelet alkalmazásában térnek el egymástól: összehasonlítás – két sorozatelem viszonyának meghatározása, mozgatás – az elemek sorrendjének változtatá-sa a rendezettségnek megfelelően. A hatékonyság vizsgálatakor is ez a két művelet, valamint az igényelt tárterület érdekes számunkra.

Minimumkiválasztásos-rendezés Először megkeressük az egész tömb legkisebb elemét, és ezt kicseréljük az első elemmel. Most már csak a maradék: 2..N részt kell rendeznünk. Megkeressük itt is a legkisebb elemet, majd ezt kicseréljük a másodikkal. Folytassuk ezt a procedúrát. Utolsó lépésként az utolsó előtti helyre kell kiválasztanunk a legkisebb elemet, hiszen ezzel az utolsó is a helyére kerül.

algoritmus Minimumkiválasztásos_rendezés konstans N=maximális_elemszám változó A:tömb[1..N] Elemtípus változó I, J, MinIndex: egész változó Csere: Elemtípus ciklus I:=1..N-1 ismétel MinIndex:=I ciklus J:=I+1..N ismétel ha A[J]<A[MinIndex] akkor MinIndex:=J hvége cvége ha MinIndex<>I akkor Csere:=A[I]; A[I]:=A[MinIndex]; A[MinIndex]:=Csere; algoritmus vége

Minimumkiválasztásos-rendezés – hatékonyság Helyfoglalás: n+1 (n elemű tömb és a cserékhez szükséges segédváltozó) Összehasonlítások száma: n*(n-1)/2 nagyságrendben n2: O(n2) Cserék száma: 0..n-1 értékadások száma: 0..3*(n-1)

Nagy ordó – O(f(n)) Az O(f(n)) jelölést (nagy ordó) rendszerint pozitív egész n-eken értelmezett f függvény esetén használjuk. Az O(f(n)) jelölés az n-től függő mennyiségek becslésére szolgál. Egy X mennyiség helyére akkor írhatunk O(f(n))-t, ha létezik olyan konstans, mondjuk M, hogy minden elég nagy n-re, |X|  M · |f(n)|, azaz aszimptotikusan felső becslést adunk egy konstansszorzótól eltekintve a lépésszámra.

A ha Min<>I akkor elágazást kihagyhatjuk az algoritmusból A ha Min<>I akkor elágazást kihagyhatjuk az algoritmusból. Ezt akkor célszerű megtenni, ha az elemek , mint a negyede van eleve a helyén. A minimumkiválasztásos rendezés már egy javításának tekinthető az egyszerű cserés rende-zésnek, mely az egyik legkevésbé hatékony rendezés, túl sok felesleges cserét tartalmaz: kevesebb ciklus I:=1..N-1 ismétel ciklus J:=I+1..N ismétel ha A[J]<A[I] akkor Csere:=A[I]; A[I]:=A[J]; A[J]:=Csere hvége cvége

Buborékrendezés Az előzőhöz képest a különbség az össze-hasonlításokban van. Ennél mindig két szomszédos elemet hasonlítunk össze, és ha nem megfelelő a sorrendjük, megcseréljük őket.

Buborékrendezés algoritmusa algoritmus Buborékrendezés változó I, J: egész változó Csere: Elemtípus ciklus I:=N..2 lépésköz -1 ismétel ciklus J:=1..I-1 ismétel ha A[J]>A[J+1] akkor Csere:=A[J]; A[J]:=A[J+1]; A[J+1]:=Csere hvége cvége algoritmus vége

Buborékrendezés – hatékonyság Helyfoglalás: n+1 (n elemű tömb és a cserékhez szükséges segédváltozó) Összehasonlítások száma: n*(n-1)/2 nagyságrendben n2: O(n2) Cserék száma: 0..n*(n-1)/2; értékadások száma: 0..3*n*(n-1)/2

Cserék átlagos számának meghatározása A cserék száma megegyezik az A tömb elemei között fennálló inverziók számával. Valóban, minden csere pontosan egy inverziót szüntet meg a két szomszédos elem között, újat viszont nem hoz létre. A rendezett tömbben pedig nincs inverzió. Feltesszük, hogy a rendezendő számok minden permutációja egyformán valószínű (vehetjük úgy, hogy az 1, 2, ..., n számokat kell rendeznünk). A cserék számának átlagát nyilvánvalóan úgy kapjuk, hogy az 1, 2, ..., n elemek minden permutációjának inverziószámát összeadjuk és osztjuk a permutációk számával (n!).

Tehát a keresett hányados: Célszerű párosítani a permutációkat úgy, hogy mindegyikkel párba állítjuk az inverzét, pl. az 1423 és a 3241 alkot egy ilyen párt. Egy ilyen párban az inverziók száma együtt éppen a lehetséges -t teszi ki: pl. inv(1423) + inv(3241) = 2+4 = 6. Tehát a keresett hányados: Tehát a buborékrendezés nagyságrendben n2-es algoritmus. Szerencsétlen esetben tehát ez a módszer rosszabb a minimumkiválasztásosnál. n 2 n 2 n 2 (n!/2) /n! = /2 = n(n-1)/4 = O(n2)

Javított buborékrendezés I. Ötlet: ha egy teljes belső ciklus lefutása alatt egyetlen csere sem volt, akkor az ez utáni menetekben sem lehet, tehát a sorozat már rendezetté vált. Ezzel kiküszöböltük a már feleslegessé vált összehasonlításokat.

Javított buborékrendezés I. algoritmus JavítottBuborékrendezés1 változó I, J: egész változó Csere: Elemtípus változó Vége: logikai I:=N; Vége:=hamis amíg (I>=2) és (nem Vége) ismétel Vége:=igaz; ciklus J:=1..I-1 ismétel ha A[J]>A[J+1] akkor Csere:=A[J]; A[J]:=A[J+1]; A[J+1]:=Csere Vége:=hamis hvége cvége I:=I-1 avége algoritmus vége

Javított buborékrendezés – hatékonyság Helyfoglalás: n+1 (n elemű tömb és a cserékhez szükséges segédváltozó) Összehasonlítások száma: n-1..n*(n-1)/2 Értékadások száma: 0..3*n*(n-1)/2 Buborékrendezés hatékonyság

Javított buborékrendezés II. Ötlet: ha a belső ciklusban volt csere, de a legutolsó valahol a sorozat belsejében volt, akkor azon túl már rendezett a sorozat. Jegyezzük meg az utolsó csere helyét, és legközelebb csak addig rendezzünk. Ez a megoldás tartalmazza az előző javítást is, ha nem volt csere, akkor befejeződik.

Javított buborékrendezés II. algoritmus JavítottBuborékrendezés2 változó I, J, UtolsóCsere: egész változó Csere: Elemtípus I:=N; amíg I>=2 ismétel UtolsóCsere=0; ciklus J:=1..I-1 ismétel ha A[J]>A[J+1] akkor Csere:=A[J]; A[J]:=A[J+1]; A[J+1]:=Csere UtolsóCsere:=J hvége cvége I:=UtolsóCsere avége algoritmus vége A konkrét számokat tekintve a hatékonysági mutatók ugyanazok, mint az előzőnél, azonban az előző javításhoz képest az átlagos végrehajtási idő tovább csökkenhet.

Beszúró rendezés Más néven beillesztő vagy kártyás rendezés. A működést leginkább a kártyalapok egyenként való kézbe vételéhez és a helyükre igazításához hasonlíthatjuk. Vesszük a soron következő elemet, és megkeressük a helyét a tőle balra lévő, már rendezett részben. A kereséssel párhuzamosan a nagyobb elemeket rendre eggyel jobbra mozgatjuk. Az aktuális elemet egy segédváltozóban tároljuk, mert a mozgatások során értéke felülíródhat egy nagyobb elemmel.

algoritmus Beszúrórendezés változó I, J: egész változó X: Elemtípus ciklus I:=2..N ismétel J:=I-1; X:=A[I] amíg (J>=1) és (X<A[J]) ismétel A[J+1]:=A[J] J:=J-1 avége A[J+1]:=X cvége algoritmus vége Hatékonyság: Helyfoglalás: n+1 (n elemű tömb és a cserékhez szük-séges segédváltozó) Összehasonlítások száma: n-1..n*(n-1)/2 Értékadások száma: 2*(n-1).. 2*(n-1)+n*(n-1)/2

Beszúró rendezés - előnyök Hatékony kis adatsorok esetén Hatékony, ha az adatsorok már részben rendezettek Gyakorlatban hatékonyabb a többi O(n2)-es rendezésnél Online algoritmus, képes rendezni egy listát az új elemek felvételekor

Shell rendezés Nem önálló módszer, hanem több, már megismert módszerhez illeszthető. Donald Shell, 1959 Elve: sokat javíthat a rendezésen, ha először az egymástól nagy távolságra lévő elemeket hasonlítjuk, cseréljük, mert így az egyes elemek gyorsabban közel kerülhetnek a végleges helyükhöz. Így az eredeti módszer hatékonyabbá válhat. Különösen igaz ez a beszúró rendezésnél.

Shellsort

Az elemek közötti távolságot jelöljük D-vel. Első értéke: N/3+1, majd D:=D/3+1. Pl. 10 elemű sorozatnál az alábbi részsorozatokat rendezzük: D=4 1,5,9 2,6,10 3,7 4,8 D=2 1,3,5,7,9 2,4,6,8,10 D=1 1,2,3,4,5,6,7,8,9,10 Úgy tűnhet, mintha D=1 esetén lezajlana az egész beszúró rendezés, ekkor azonban már a korábbi menetek miatt minimális számú össze-hasonlítás és mozgatás történik.

algoritmus ShellBeszúrórendezés változó I, J, D, E: egész változó X: Elemtípus D:=N ismétel D:=D/3+1 ciklus E:=1..D ismétel I:=E+D amíg I<=N ismétel J:=I-D; X:=A[I] amíg (J>=1) és (X<A[J]) ismétel A[J+D]:=A[J] J:=J-D avége A[J+D]:=X I:=I+D cvége ivége D=1 esetén algoritmus vége

Shell rendezés hatékonysága Kevesebb, mint O(n2) összehasonlítást és cserét igényel Nehéz megállapítani a műveletigényét: Megvalósítástól függően O(n1.25) és O(n1.5) között van

Indexvektoros rendezés A rendezendő tömb elemeit nem mozgatjuk, hanem a tömbhöz egy indexvektort rendelünk, melyben a tömb elemeire mutató indexek a tömb rendezettségének megfelelően követik egymást. Az eljárás során az indextömb elemeit az indexelt adatok rendezettségének függvényében sorba rakjuk. A hasonlítást tehát mindig az indexelt adatokra végezzük el, de csere esetén csak az indexeket cseréljük. Így az eredeti tömbünk változatlan maradhat. Közvetett módon így egyszerre több szempont szerint is módunkban áll adatainkat rendezni.

algoritmus Indexvektoros_Minimumkiválasztásos_rendezés konstans N=maximális_elemszám változó A:tömb[1..N] Elemtípus változó Index:tömb[1..N] egész változó I, J, Min, Csere: egész ciklus I:=1..N ismétel Index[I]:=I; cvége ciklus I:=1..N-1 ismétel Min:=I ciklus J:=I+1..N ismétel ha A[Index[J]]<A[Index[Min]] akkor Min:=J hvége ha Min<>I akkor Csere:=Index[I]; Index[I]:=Index[Min]; Index[Min]:=Csere; algoritmus vége

Gyorsrendezés (Quicksort) Elve rekurzív: osszuk két részre a rendezendő sorozatot úgy, hogy az egyik rész minden eleme kisebb legyen a másik rész összes eleménél; a két részre külön-külön ismételjük meg az előbbi lépést, míg mindkét rész 0 vagy 1 elemű lesz. A feldolgozási művelet egy szétválogatás, melynek során egy megadott értékhez viszonyítva a tőle kisebb elemeket elé, a nagyobbakat mögé helyezzük. Viszonyítási értéknek a gyakorlatban a sorozat középső vagy első elemét választják ki. Hatékonyság: O(n log n)

Quicksort

eljárás GyorsRendezés(Alsó, Felső: egész) változó I, J: egész változó: X, Csere: ElemTípus I:=Alsó; J:=Felső X:=A[(Felső+Alsó)/2] ismétel amíg A[I]<X ismétel I:=I+1 avége amíg A[J]>X ismétel J:=J-1 ha I<J akkor Csere:=A[I]; A[I]:=A[J]; A[J]:=Csere hvége ha I<=J akkor I:=I+1; J:=J-1 ivége I>J esetén ha Alsó<J akkor GyorsRendezés(Alsó, J) hvége ha I<Felső akkor GyorsRendezés(I, Felső) hvége eljárás vége

4.3. Keresések A probléma általános megfogalmazása: adott egy N elemű sorozat, keressük meg azt az elemet (határozzuk meg a helyét a sorozatban), mely megfelel egy megadott tulajdonságnak. Ha több ilyen van, akkor a keresőalgoritmusok általában az első ilyen elemet találják meg. A konkrét megvalósításoknál mi egy adott értéket keresünk.

Lineáris keresés Más néven: szekvenciális keresés. Elölről kezdve sorra vizsgáljuk a sorozat elemeit. A keresés sikertelenségét jelzi, hogy a sorozat végére érve nem találtuk meg a keresett adatot.

a, Rendezetlen sorozatban algoritmus Szekvenciális_keresés változó I, Hely:egész változó Adat: ElemTípus változó Talált: logikai I:=1 amíg (I<=N) és (A[I]<>Adat) ismétel I:=I+1 avége Talált := I<=N ha Talált akkor Hely:=I hvége algoritmus vége N elemű sorozat esetén minimum 1, maximum N, átlagosan (N+1)/2 ciklusvégrehajtás után találja meg a keresett elemet; vagy N összehason-lítás után derül ki, hogy nincs meg a keresett elem.

b, Rendezett sorozatban algoritmus Rendezett_Szekvenciális_keresés változó I, Hely:egész változó Adat: ElemTípus változó Talált: logikai I:=1 amíg (I<=N) és (A[I]<Adat) ismétel I:=I+1 avége Talált := (I<=N) és (A[I]=Adat) ha Talált akkor Hely:=I hvége algoritmus vége Az előzőhöz képest növeli a hatékonyságot, hogy akkor is leáll a keresés, ha nagyobb elemre lépünk, mint a keresett érték. Viszont hátrány, hogy előfeltétel a rendezettség.

c, Keresési gyakoriság szerint Rendezhető a sorozat keresési gyakoriság szerint is (konyhapolc elv). Ekkor az a, algoritmus átlagosan kevesebb, mint (N+1)/2 ciklusvégrehajtás után találja meg a keresett elemet. Gyakoriság szerint rendezhetünk: Létrehozunk egy párhuzamos számlálótömböt, és időnként ez alapján csökkenő sorrendbe rendezzük az adattömböt. Önszerveződő struktúra: valahányszor sikeresen megtaláltunk egy elemet, az eredetileg előtte lévőket eggyel hátrébb léptetjük, majd azt a sorozat legelejére helyezzük.

d, Ütközős (strázsás) keresés A kereső ciklus összetett feltételét egyszerűsítjük le. A sorozat végére felvesszük a keresett adatot, így felesleges vizsgálni, hogy túlhaladtunk-e a sorozaton (I<=N), hiszen mindenképpen megtaláljuk a keresett elemet. Főképp nagy elemszámú sorozatoknál hatéko-nyabb az egyszerű lineáris keresésnél, mivel a ciklusfeltétel kiértékelése lényegesen rövidebb lesz.

algoritmus Strázsás_Szekvenciális_keresés változó I, Hely:egész változó Adat: ElemTípus változó Talált: logikai A[N+1]:=Adat I:=1 amíg A[I]<>Adat ismétel I:=I+1 avége Talált := I<=N ha Talált akkor Hely:=I hvége algoritmus vége

Bináris keresés Más néven: felezéses keresés. Csak rendezett sorozaton valósítható meg. Algoritmus: Meghatározzuk a középső elemet, majd megvizsgáljuk ez-e a keresett. Ha nem, akkor ha a keresett kisebb a középsőnél, akkor a sorozat alsó, egyébként a felső részébe folytatjuk a keresést. A keresés két esetben fejeződhet be: megtaláltuk a keresett adatot; a részsorozat alsó indexe (E) nagyobb a felső (U), nincs benne a sorozatban a keresett adat.

algoritmus Bináris_keresés változó Alsó, Felső, Közép, Hely:egész változó Adat: ElemTípus változó Talált: logikai Alsó:=1; Felső:=N; Közép:=(Alsó+Felső)/2 amíg (Alsó<=Felső) és (A[Közép]<>Adat) ismétel ha Adat<A[Közép] akkor Felső:=Közép-1 különben Alsó:=Közép+1 hvége Közép:=(Alsó+Felső)/2 avége Talált := Alsó<=Felső ha Talált akkor Hely:=Közép

Szokásos logaritmikus keresésnek is nevezni, mivel 2k elemű sorozatot k lépésben vizsgálhatunk végig. Tehát egy n elemű sorozatnál átlagosan log2n hasonlítás után találja meg az elemet, vagy derül ki, hogy nincs ilyen. Ez egymillió elem esetén kb. 20 lépést jelent, tehát igen látványos a különbség a lineáris módszerhez képest. Probléma lehet a rendezettség fenntartása mellett az, hogy nem minden adatszerkezetnél címezhető meg a középső elem (pl. láncolt lista).

Bár nem olyan hatékony, de kínálja magát a rekurzív megoldás: eljárás BinKeres(Alsó, Felső: egész) változó Közép, Hely:egész ha Alsó<=Felső akkor Közép:=(Alsó+Felső)/2 elágazás amikor Adat<A[Közép]: BinKeres(Alsó,Közép-1) amikor Adat>A[Közép]: BinKeres(Közép+1,Felső) különben Talált:=Igaz Hely:=Közép evége Talalt:=Hamis hvége eljárás vége

5. Verem A verem (angolul: stack) homogén adatelemek olyan sorozata, amelyen két művelet értelmezett: új elem elhelyezése a verem tetejére (push) elem kivétele a verem tetejéről (pop). Működése LIFO (Last In First Out) elvű.

Objektum orientált módszertannal készítsünk egy verem osztályt, melynek adattagjai: az elemek tárolására szolgáló tömb, indexek, melyek a verem aljára ill. tetejére mutatnak, a verem (tömb) mérete. Metódusai: konstruktor, verembe (push), veremből (pop): műveletek, tele, ures: állapot lekérdezések. Megj. Példánkban a verem alja megegyezik a tömb aljával, így az alja mutató csak a szemléletességet szolgálja. Tömb helyett dinamikus helyfoglalású adatszerkezetet, láncolt listát is használhatnánk.

class Verem{ private int max; private int[]elem; private final int alja=0; private int teteje; public Verem(int max){ elem=new int[max]; this.max=max; teteje=-1; } public boolean ures(){ return teteje<alja; public boolean tele(){ return teteje==max-1;

public boolean verembe(int adat){ if(!tele()){ elem[++teteje]=adat; return true; }else return false; } public int verembol(){ /* if(ures()){ Hibajelzés }else */ return elem[teteje--];

Egy példa a vermünk használatára: public class VeremProgram{ public static void main(String[]args){ Verem verem=new Verem(100); for(int i=1; i<=10; i++) verem.verembe(i); if(!verem.ures()) System.out.print(verem.verembol()+" "); }

Nagyon meglepő lenne, ha a több ezer osztályból álló Java API nem tartalmazna verem implementációt. A számos adatszerkezetet realizáló java.util csomagban találjuk a Stack osztályt. Egy példa a használatára: import java.util.*; public class VeremProgram2{ public static void main(String[]args){ Stack verem=new Stack(); for(int i=1; i<=10; i++){ verem.push(new Integer(i)); verem.push("Szoveg"+i); } for(int i=1; i<=20; i++) System.out.println(verem.pop());

6. Sor A sor (angolul: queue) homogén adatele-mek olyan sorozata, amelyen két művelet értelmezett: új elem elhelyezése a sor végére (put) elem kivétele a sor elejéről (get). Működése FIFO (First In First Out) elvű. Mindazon feladatok megoldására alkalmas, ahol sorban állást kell megvalósítanunk.

Objektum orientált módszertannal készítsünk egy sor osztályt, melynek adattagjai: az elemek tárolására szolgáló tömb, indexek, melyek a sor első ill. utolsó elemére mutatnak, a sor (tömb) mérete. Metódusai: konstruktor, sorba (put), sorból (get): műveletek, tele, ures: állapot lekérdezések. Ciklikus sort készítünk, tehát ha az utolsó mutató eléri a tömb végét, akkor ugrik a tömb elejére, feltéve, hogy még nincs tele a sor. Ha a sor kiürül, mindig alaphelyzetbe állítjuk, amikor az utolsó=-1, első=0.

class Sor{ private int max; private int[]elem; private int elso; private int utolso; public Sor(int max){ elem=new int[max]; this.max=max; elso=0; utolso=-1; } public boolean ures(){ return utolso==-1; public boolean tele(){ return elso==0 && utolso==max-1 || utolso>-1 && utolso==elso-1;

public boolean sorba(int adat){ if(!tele()){ if(utolso<max-1) utolso++; else utolso=0; elem[utolso]=adat; return true; }else return false; }

public int sorbol(){ /* if(ures()){ Hibajelzés }else */ int adat=elem[elso]; //ha a sor üressé válik, alaphelyzetbe állítás if(elso==utolso){ elso=0; utolso=-1; }else if(elso<max-1) elso++; else elso=0; return adat; }

Egy példa az osztály tesztelésére: public class SorProgram{ public static void main(String[]args){ Sor sor=new Sor(4); sor.sorba(1);sor.sorba(2);sor.sorba(3); System.out.println(sor.sorbol()+" "+sor.sorbol()+" "); System.out.println(sor.ures()); sor.sorba(4);sor.sorba(5); System.out.println(sor.sorbol()+" "+sor.sorbol()+" "+ sor.sorbol()); sor.sorba(6);sor.sorba(7); System.out.println(sor.sorbol()+" "+sor.sorbol()); }

7. Halmaz Cél a matematikai halmaznak illetve a halmazelmélet műveleteinek a realizálása. Objektum orientált módszertannal készítsünk egy halmaz osztályt, melynek adattagjai: az elemek tárolására szolgáló tömb, a halmaz elemszáma, a halmaz (tömb) „mérete”. Metódusai: konstruktor, tele, ures, eleme-e: állapot lekérdezések, betesz, metszet, unió, különbség, részhalmaz vizsgálat: halmazműveletek, toArray, toString.

class Halmaz{ private int max; private int[]elem; private int elemszam; public Halmaz(int max){ elem=new int[max]; this.max=max; elemszam=0; } public boolean ures(){ return elemszam==0; public boolean tele(){ return elemszam==max;

public boolean eleme(int adat){ int i=0; while(i<max && elem[i]!=adat) i++; return i<max; } public boolean betesz(int adat){ if(!tele() && !eleme(adat)){ elem[elemszam++]=adat; return true; }else return false;

public Halmaz metszet(Halmaz h){ Halmaz m=new Halmaz(max); for(int i=0; i<elemszam; i++) if(h.eleme(elem[i])) m.betesz(elem[i]); return m; } public Halmaz unio(Halmaz h){ Halmaz u=new Halmaz(max+h.max); u.betesz(elem[i]); for(int i=0; i<h.elemszam; i++) u.betesz(h.elem[i]); return u; public Halmaz kulonbseg(Halmaz h){ Halmaz k=new Halmaz(max); if(!h.eleme(elem[i])) k.betesz(elem[i]); return k;

public boolean reszhalmaza(Halmaz h){ if(elemszam>h.elemszam) return false; else{ int i=0; while(i<elemszam && h.eleme(elem[i])) i++; return i==elemszam; } public String toString(){ String s=elemszam+" elem:"; for(int i=0;i<elemszam;i++) s+=" "+elem[i]; return s;

Egy példa az osztály tesztelésére:  public class HalmazProgram{ public static void main(String[]args){ Halmaz h1, h2; h1=new Halmaz(10); h2=new Halmaz(10); for(int i=1;i<=7;i++) h1.betesz(i); for(int i=5;i<=10;i++) h2.betesz(i); System.out.println("h1: "+h1); System.out.println("h2: "+h2); System.out.println("h1 U h2: "+h1.unio(h2)); System.out.println("h1 metszete h2-vel: "+h1.metszet(h2)); System.out.println("h1-h2: "+h1.kulonbseg(h2)); if(h1.reszhalmaza(h2)) System.out.println("h1 reszhalmaza h2-nek:"); else System.out.println("h1 nem reszhalmaza h2-nek:"); if(h2.reszhalmaza(h1)) System.out.println("h2 reszhalmaza h1-nek:"); System.out.println("h2 nem reszhalmaza h1-nek:"); }

8. Láncolt lista Gazdaságos memóriafoglalás, egyszerű karbantartási műveletek (törlés, beszúrás). Szekvenciális adatszerkezet. Listafej: a lista első elemére mutat. Végjel (null): speciális mutató érték, az utolsó elem mutatórészében állva jelzi a lánc végét.

Egy listaelem szerkezete típus ListaElem: rekord( Érték: ÉrtékTípus; Köv: MutatóTípus //mely a ListaElem-re képes mutatni )

Strázsás (ütközős) lista A lista végére egy üres listaelemet (veg) lánco-lunk. Ezzel és más megoldásokkal a következő kényel-metlenségeket küszöböljük ki: a lista végén végzett műveletekhez nem kell végigfutni a listán; egy elem törlésekor elég a törlendő elem címét ismerni, nincs szükség a megelőző elemre; egy adott elem elé tudunk beszúrni; beszúrás, törlés hasonló a lista elején, közepén, végén.

//Egy listaelem osztálya class Elem{ private int ertek; private Elem kov; public Elem(){ kov=null; } public int getErtek(){ return ertek;   public Elem getKov(){ return kov; public void setErtek(int ertek){ this.ertek=ertek;   public void setKov(Elem kov){ this.kov=kov;

class LancoltLista{ private Elem fej, veg; public LancoltLista() { fej=new Elem(); veg=fej; } public Elem getFej(){ return fej;   public Elem getVeg(){ return veg;

veg.setErtek(adat);//strázsás keresés p=fej; while(p.getErtek()!=adat) public Elem keres(int adat){ Elem p; veg.setErtek(adat);//strázsás keresés p=fej; while(p.getErtek()!=adat) p=p.getKov(); if(p==veg) return null; else return p; }

//jó a sor elején, közepén, végén //trükk: valójában az új, üres elemet a megadott //mögé fűzzük //jó a sor elején, közepén, végén public void fuzEle(Elem ezEle, int adat){ Elem p=new Elem(); //ezEle átmásolása az új elembe (p-be) p.setErtek(ezEle.getErtek()); p.setKov(ezEle.getKov()); //az adat beírása ezEle-be ezEle.setErtek(adat); ezEle.setKov(p); if(veg==ezEle) veg=p; }

//hanem az azt követőt töröljük public void torol(Elem ezt){ //fizikailag nem a megadott elemet, //hanem az azt követőt töröljük public void torol(Elem ezt){ //a törlendőt követő elem átmásolása a törlendőbe if(veg==ezt.getKov()) veg=ezt; ezt.setErtek((ezt.getKov()).getErtek()); ezt.setKov((ezt.getKov()).getKov()); } public boolean torol(int ertek){ Elem p=keres(ertek); if(p==null) return false; else{ torol(p); return true;

public void fuzElejere(int adat){ fuzEle(fej,adat); public void fuzVegere(int adat){ fuzEle(veg,adat); }   public void fuzElejere(int adat){ fuzEle(fej,adat); public String toString(){ String s="Elemek:"; Elem p=fej; while(p!=veg){ s+=" "+p.getErtek(); p=p.getKov(); return s;

További láncoltlista változatok rendezett láncolt lista: nem utólag rendezzük a listát, hanem az új elem felvitele a rendezettség megtartása mellett történik; ciklikusan láncolt lista: az utolsó elem mutatója az első elemre mutat; két irányban láncolt lista: egy listaelemben két mutató; többszörösen láncolt lista: több láncolat mentén is bejárható, azaz több szempont szerint is rendezett, egy elemben több mutató.

9. Fa A fa az adatok hierarchikus kapcsolatának ábrázolására alkalmas adatszerkezet (pl. háttértárolók könyvtárszerkezete). Rendelkezik egy kitüntetett kezdőponttal, és e kezdőpontból kiindulva minden adatelemhez tetszőleges számú új elem kapcsolódhat. A kapcsolódó elemek a fa más részeihez nem kapcsolódhatnak.

Elnevezések gyökér: a kezdőelem; csomópontok: adatelemek; élek: egymással közvetlen kapcsolatban lévő csomópontokat kötik össze, irányuk mindig a gyökértől a távolabbi csomópont felé mutat; levél: azon csomópontok, amelyekből nem vezet tovább él; út: egy csomópontból egy másikba vezető élsorozat; szülő: ha A csomópontból él mutat B csomópontba, akkor A szülője B-nek; gyerek: ha A csomópontból él mutat B csomópontba, akkor B gyereke A-nak; testvér: egy szülőhöz tartozó csomópontok.

9.1. Bináris fa Bináris fa: minden csomópontnak legfeljebb két gyereke van. Szigorúan bináris fa: a levélelemek kivételé-vel minden csomópontnak pontosan két gyereke van.

A bináris fa megvalósítása Tárbeli megvalósítása a láncolt listában alkalmazott adatszerkezet bővítésével: minden elemnek két rákövetkezője lehet, ezért két mutatót alkalmazunk a csomópontokban, az egyik a baloldali, a másik a jobboldali részfa gyökerére mutat. Ha valamely mutató értéke a VégJel (null), akkor ebben az irányban nincs folytatása a fának. A levélelemek mindkét mutatója VégJel.

Egy csomópont szerkezete típus BinFaElem: rekord( Érték: ÉrtékTípus; Bal, Jobb: MutatóTípus //mely a BinFaElem-re képes mutatni ) Minden fához tartozik egy változó: Gyökér, mely a fa kezdőpontjára, a gyökérelemre mutat. Ez a mutató fogja azonosítani a fát.

Bináris fa bejárása Bejárásnak nevezzük azt a folyamatot, amikor a fa minden elemét pontosan egyszer érintve feldolgozzuk. Erre a gyakorlatban három, a rekurzív definíciókra támaszkodó módszer terjedt el: preorder bejárás: gyökérelem feldolgozása; baloldali részfa preorder bejárása; jobboldali részfa preorder bejárása; inorder bejárás: baloldali részfa inorder bejárása; jobboldali részfa inorder bejárása; postorder bejárás: baloldali részfa postorder bejárása; jobboldali részfa postorder bejárása;

+ a * b c Példa: Algebrai kifejezések (pl. a*b+c) ábrázolása, bejárása. Az ilyen típusú felírásban a fa levelei az operandusokat, a többi csomópont pedig az operátorokat tartalmazza. A háromféle bejárás szerint feldolgozva az elemeket, az algebrai kifejezések ismert formáit kapjuk: preorder bejárással a prefix alakot: +*abc; inorder bejárással az infix alakot: a*b+c; postorder bejárással a postfix alakot: ab*c+;

A bejáró rekurzív algoritmusok (Elem[P]-vel jelöljük a P által mutatott csomópontot). eljárás BinFaPreorder(P: MutatóTípus) ha P<>VégJel akkor Elem[P].Érték feldolgozása BinFaPreorder(Elem[P].Bal) BinFaPreorder(Elem[P].Jobb) hvége eljárás vége

eljárás BinFaInorder(P: MutatóTípus) ha P<>VégJel akkor BinFaInorder(Elem[P].Bal) Elem[P].Érték feldolgozása BinFaInorder(Elem[P].Jobb) hvége eljárás vége   eljárás BinFaPostorder(P: MutatóTípus) BinFaPostorder(Elem[P].Bal) BinFaPostorder(Elem[P].Jobb)

A csomópont adatszerkezetének és a bejáró algoritmusoknak az implementációja: class Csomopont{ private char ertek; private Csomopont bal,jobb; public Csomopont(char ertek,Csomopont bal,Csomopont jobb){ this.ertek=ertek; this.bal=bal; this.jobb=jobb; } public char getErtek(){ return ertek;   public Csomopont getBal(){ return bal; public Csomopont getJobb(){ return jobb;

class BinFa{ public static void bejarPreorder(Csomopont p){ if(p!=null){ System.out.print(p.getErtek()); bejarPreorder(p.getBal()); bejarPreorder(p.getJobb()); } public static void bejarInorder(Csomopont p){ bejarInorder(p.getBal()); bejarInorder(p.getJobb()); public static void bejarPostorder(Csomopont p){ bejarPostorder(p.getBal()); bejarPostorder(p.getJobb());

A példa algebrai kifejezésének ábrázolása és bejárása: public class BinFaProgram{ public static void main(String[]args){ Csomopont a=new Csomopont('a',null,null); Csomopont b=new Csomopont('b',null,null); Csomopont c=new Csomopont('c',null,null); Csomopont gyoker=new Csomopont('+',new Csomopont('*',a,b),c); BinFa.bejarPreorder(gyoker); System.out.println(); BinFa.bejarInorder(gyoker); BinFa.bejarPostorder(gyoker); }

9.2. Keresőfa Gyors keresési módszerekben illetve az adattömörítésben alkalmazzák. A keresőfa egy olyan bináris fa, amelynek minden csomó-pontjára igaz, hogy a benne tárolt érték: nagyobb, mint a baloldali részfájában tárolt bármely érték; kisebb, mint a jobboldali részfájában tárolt bármely érték. Ha az adatok ismétlődését is megengedjük, akkor a felté-telek enyhíthetők kisebb vagy egyenlőre illetve nagyobb vagy egyenlőre.

Az ábrán megfigyelhető, hogy inorder bejárás szerint az eredmény egy rendezett számsorozat lesz.

Keresés a keresőfában A keresés során a keresőfa definícióját (rendezettség) használjuk ki. algoritmus KeresőfaKeres változó P: MutatóTípus; P:=Gyökér amíg(P<>Végjel) és (Elem[P].Érték<>Adat) ismétel ha Adat< Elem[P].Érték akkor P:=Elem[P].Bal különben P:=Elem[P].Jobb hvége avége Talált:=P<>Végjel ha Talált akkor Hely:=P algoritmus vége

9.3. Általános fák megvalósítása Egy elemnek tetszőleges számú gyereke (vagyis tetszőleges számú testvére lehet). Alkalmazhatunk láncolt listát: fűzzük listába a testvér csomópontokat, így a szülőtől csak egyetlen mutatónak kell megcímeznie ezt a listát. Természetesen a szülő maga is része egy hasonló listának, ami a testvéreivel kapcsolja össze. Minden csomópontban két mutatóra lesz szükség: az egyik mutat a legelső gyerekre, a másik a következő testvérre. Így az általános fák kezelését visszavezettük a bináris fákéra.

Az első ábrán látható könyvtárszerkezete ily módon ábrázoljuk a memóriában: