Bevezetés az algoritmikába

Hasonló dokumentumok
Tartalomjegyzék Algoritmusok - pszeudókód

Algoritmusok pszeudókód... 1

Tartalomjegyzék Algoritmusok - pszeudókód

Algoritmusok pszeudókód... 1

Algoritmusok - pszeudókód... 1

Egyszerű programok készítése Kifejezések Bitszintű műveletek Relációs műveletek... 58

Felvételi tematika INFORMATIKA

4. Előfeltételek (ha vannak) 4.1 Tantervi Nincs 4.2 Kompetenciabeli Feladatok kijelentéseinek megértése

Webprogramozás szakkör

Java programozási nyelv

Algoritmusok. Dr. Iványi Péter

Brósch Zoltán (Debreceni Egyetem Kossuth Lajos Gyakorló Gimnáziuma) Számelmélet I.

Felvételi vizsga mintatételsor Informatika írásbeli vizsga

Gyakorló feladatok az 1. nagy zárthelyire

A programozás alapjai előadás. Amiről szólesz: A tárgy címe: A programozás alapjai

A rész (30 pont) A.1. Vajon mit csinál? (5 pont) A generál(n) algoritmus egy n természetes számot dolgoz fel (0 < n < 100).

BABEŞ BOLYAI TUDOMÁNYEGYETEM MATEMATIKA ÉS INFORMATIKA KAR BBTE Matek-Infó verseny 1. tételsor INFORMATIKA írásbeli. A versenyzők figyelmébe:

Algoritmusok Tervezése. 6. Előadás Algoritmusok 101 Dr. Bécsi Tamás

I. ALAPALGORITMUSOK. I. Pszeudokódban beolvas n prim igaz minden i 2,gyök(n) végezd el ha n % i = 0 akkor prim hamis

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

Információk. Ismétlés II. Ismétlés. Ismétlés III. A PROGRAMOZÁS ALAPJAI 2. Készítette: Vénné Meskó Katalin. Algoritmus. Algoritmus ábrázolása

Programozás I. Sergyán Szabolcs Óbudai Egyetem Neumann János Informatikai Kar szeptember 10.

Programozási segédlet

Programozás I. 1. előadás: Algoritmusok alapjai. Sergyán Szabolcs

Bevezetés a programozásba I 3. gyakorlat. PLanG: Programozási tételek. Programozási tételek Algoritmusok

Algoritmusokfelülnézetből. 1. ELŐADÁS Sapientia-EMTE

2018, Diszkrét matematika

Programozási tételek. PPT 2007/2008 tavasz.

ALGORITMIKUS SZERKEZETEK ELÁGAZÁSOK, CIKLUSOK, FÜGGVÉNYEK

Egész számok. pozitív egész számok: 1; 2; 3; 4;... negatív egész számok: 1; 2; 3; 4;...

Szoftvertervezés és -fejlesztés I.

Változók. Mennyiség, érték (v. objektum) szimbolikus jelölése, jelentése Tulajdonságai (attribútumai):

9. előadás. Programozás-elmélet. Programozási tételek Elemi prog. Sorozatszámítás Eldöntés Kiválasztás Lin. keresés Megszámolás Maximum.

Változók. Mennyiség, érték (v. objektum) szimbolikus jelölése, jelentése Tulajdonságai (attribútumai):

Megjegyzés: A programnak tartalmaznia kell legalább egy felhasználói alprogramot. Példa:

Programozás I. Sergyán Szabolcs Óbudai Egyetem Neumann János Informatikai Kar szeptember 10.

AZ ALGORITMUS. az eredményt szolgáltatja

BABEŞ-BOLYAI TUDOMÁNYEGYETEM MATEMATIKA-INFORMATIKA KAR Felvételi verseny - minta Informatika írásbeli

A félév során előkerülő témakörök

Egyszerű programozási tételek

Matematika. 1. évfolyam. I. félév

BBTE Matek-Infó verseny mintatételsor Informatika írásbeli vizsga

Programozás alapjai (ANSI C)

ÁTVÁLTÁSOK SZÁMRENDSZEREK KÖZÖTT, SZÁMÁBRÁZOLÁS, BOOLE-ALGEBRA

INFORMATIKA javítókulcs 2016

Bevezetés az informatikába

Rekurzív algoritmusok

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

Amit a törtekről tudni kell Minimum követelményszint

Programozás I. Egyszerű programozási tételek. Sergyán Szabolcs

Programozás I. Egyszerű programozási tételek. Sergyán Szabolcs

Kiegészítő részelőadás 1. Az algoritmusok hatékonyságának mérése

Informatika tanítási módszerek

Előfeltétel: legalább elégséges jegy Diszkrét matematika II. (GEMAK122B) tárgyból

Ellenőrző kérdések. 36. Ha t szintű indexet használunk, mennyi a keresési költség blokkműveletek számában mérve? (1 pont) log 2 (B(I (t) )) + t

22. GRÁFOK ÁBRÁZOLÁSA

Bánsághi Anna 2014 Bánsághi Anna 1 of 68

Adatszerkezetek. Nevezetes algoritmusok (Keresések, rendezések)

2018, Diszkre t matematika. 10. elo ada s

Bevezetés a programozásba I.

Algoritmizálás, adatmodellezés tanítása 7. előadás

HORVÁTH ZSÓFIA 1. Beadandó feladat (HOZSAAI.ELTE) ápr 7. 8-as csoport

29. Visszalépéses keresés 1.

Struktúra nélküli adatszerkezetek

Aritmetikai kifejezések lengyelformára hozása

ELEMI PROGRAMOZÁSI TÉTELEK

3 A C programozási nyelv szintaktikai egységei

Algoritmizálás. Horváth Gyula Szegedi Tudományegyetem Természettudományi és Informatikai Kar

;3 ; 0; 1 7; ;7 5; 3. pozitív: ; pozitív is, negatív is: ;

FEGYVERNEKI SÁNDOR, Valószínűség-sZÁMÍTÁs És MATEMATIKAI

Programozás alapjai 1.Gy: Algoritmizálás P R O

LEGO robotok. XII. rész

Számelmélet Megoldások

Gráfok 2. Legrövidebb utak, feszítőfák. Szoftvertervezés és -fejlesztés II. előadás. Szénási Sándor

Vezérlési szerkezetek

Programozás alapjai. 6. gyakorlat Futásidő, rekurzió, feladatmegoldás

Programtervezés. Dr. Iványi Péter

Minden egész szám osztója önmagának, azaz a a minden egész a-ra.

Kinek szól a könyv? A könyv témája A könyv felépítése Mire van szükség a könyv használatához? A könyvben használt jelölések. 1. Mi a programozás?

Babeş-Bolyai Tudományegyetem, Kolozsvár. Informatikai-matematika záróvizsga tankönyv

Algoritmusok, adatszerkezetek, objektumok

1. előadás. Lineáris algebra numerikus módszerei. Hibaszámítás Számábrázolás Kerekítés, levágás Klasszikus hibaanalízis Abszolút hiba Relatív hiba

TANMENETJAVASLAT. Dr. Korányi Erzsébet MATEMATIKA. tankönyv ötödikeseknek. címû tankönyvéhez

Alkalmazott modul: Programozás 4. előadás. Procedurális programozás: iteratív és rekurzív alprogramok. Alprogramok. Alprogramok.

Követelmény az 5. évfolyamon félévkor matematikából

Általános algoritmustervezési módszerek

1. Feladat: beolvas két számot úgy, hogy a-ba kerüljön a nagyobb

MATEMATIKA TANMENET SZAKKÖZÉPISKOLA. 9. Nyelvi előkészítő osztály

Logikai áramkörök. Informatika alapjai-5 Logikai áramkörök 1/6

Amit a törtekről tudni kell 5. osztály végéig Minimum követelményszint

26. MINIMÁLIS KÖLTSÉGŰ UTAK MINDEN CSÚCSPÁRRA

BABEŞ-BOLYAI TUDOMÁNYEGYETEM KOLOZSVÁR. Informatika záróvizsga tankönyv

Elemi matematika szakkör

Készítette: Nagy Tibor István Felhasznált irodalom: Kotsis Domokos: OOP diasor Zsakó L., Szlávi P.: Mikrológia 19.

Rekurzió. Dr. Iványi Péter

Programozás I. házi feladat

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

Programozás alapjai 9. előadás. Wagner György Általános Informatikai Tanszék

A 2017/2018 tanévi Országos Középiskolai Tanulmányi Verseny első fordulójának feladatai. INFORMATIKA II. (programozás) kategória

KOVÁCS BÉLA, MATEMATIKA I.

Átírás:

Bevezetés az algoritmikába Egyetemi jegyzet Ionescu Klára clara@cs.ubbcluj.ro Kolozsvár, 2007

Bevezetés az algoritmikába

Műszaki szerkesztő: Ionescu Klára és Buzogány László Formátuma: B5 vágott Nyomtatta és kötötte: Egyetemi Könyvkiadó Kolozsvár Szaklektorok: dr. Kása Zoltán, Buzogány László és Takács Andrea

Tartalomjegyzék Bevezetés...9 1. A SZÁMÍTÓGÉPES FELADATMEGOLDÁS LÉPÉSEI...13 1.1. A programozói tevékenység...13 1.2. A feladatmegoldás lépései számítógépes környezetben...14 1.3. Alkalmazások minőségi szempontjai...15 2. AZ ALGORITMUSOK ÁBRÁZOLÁSA...17 2.1. Algoritmusok...17 2.1.1. Az algoritmus fogalma...17 2.1.2. Az algoritmusok leírásánál használt elemek...19 2.2. Algoritmusok ábrázolása folyamatábrák és pszeudokód nyelvek segítségével...23 2.3. A strukturált programozás alapelvei...26 2.3.1. Lineáris struktúrák...27 2.3.2. Elágazási struktúrák...27 2.3.3. Ismétlő struktúrák...28 2.3.4. Az alapstruktúrák jelölése pszeudokódban...32 2.3.5. Egyszerű alapszabályok...35 2.4. A feladatok számítógépes megoldásához fűződő általános kérdések. 35 2.4.1. Algoritmusok helyessége...36 2.4.2. Az algoritmus végrehajtásához szükséges idő...39 2.4.3. Az algoritmus által feldolgozott adatok számára szükséges memória mérete...43 2.4.4. Algoritmusok egyszerűsége...43 2.4.5. Algoritmusok optimalitása...43 2.4.6. Algoritmusok létezése...44 2.5. Megoldott feladatok...45 2.5.1. Felcserélés...45 2.5.2. Maximumérték...45 2.5.3. Elnökválasztás...47 2.6. Kitűzött feladatok...49 3. LÉPÉSEK FINOMÍTÁSA...51 3.1. Bevezetés...51 3.2. Megoldott feladatok...51 3.2.1. Eukleidész algoritmusa...51 3.2.2. Prímszámok...53 3.2.3. Fibonacci-számok...59 3.2.4. Háromszög...62 3.2.5. Fordított szám...63 3.2.6. Törzstényezők...65 3.2.7. Konverzió...66

6 TARTALOMJEGYZÉK 3.2.8. Gyors hatványozás...69 3.3. Kitűzött feladatok...69 4. PROGRAMOZÁSI TÉTELEK...73 4.1. Bevezetés...73 4.2. Egyszerű programozási tételek...73 4.2.1. Összeg és szorzat...73 4.2.2. Döntés...75 4.2.3. Kiválasztás...78 4.2.4. Szekvenciális (lineáris) keresés...79 4.2.5. Megszámlálás...82 4.2.6. Minimum- és maximumkiválasztás...83 4.2.7. Kiválogatás...85 4.3. Összetett programozási tételek...87 4.3.1. Szétválogatás...87 4.3.2. Sorozat halmazzá alakítása...90 4.3.3. Keresztmetszet...92 4.3.4. Egyesítés...93 4.3.5. Összefésülés...94 4.4. Megoldott feladatok...97 4.4.1. Összeg...97 4.4.2. Párok...98 4.4.3. Arány...98 4.4.4. Hőmérséklet...98 4.4.5. Teljes négyzet...99 4.4.6. Négyzetgyök...100 4.4.7. Statisztika...101 4.4.8. Osztályfőnök...102 4.4.9. Bűvös négyzet...103 4.4.10. Maximális összegű leghosszabb részsorozat...104 4.5. Kitűzött feladatok...107 5. ALPROGRAMOK...111 5.1. Bevezetés...111 5.2. Algoritmusok és programok fejlesztési módozatai...113 5.2.1. A top-down típusú (fentről lefele) programozás...113 5.2.2. A bottom-up (lentről felfele) programozás...113 5.2.3. Moduláris algoritmustervezés...114 5.2.4. Megoldott feladat...114 5.3. A moduláris programozás alapszabályai...117 5.3.1. Moduláris dekompozíció...117 5.3.2. Moduláris kompozíció...118 5.3.3. Modulok tulajdonságai...118 5.3.4. A modularitás alapelvei...118 5.4. Algoritmusok helyességének ellenőrzése...119 5.4.1. A fekete doboz módszere...119 5.4.2. Az átlátszó doboz módszere...119 5.5. Megoldott feladatok...120

TARTALOMJEGYZÉK 7 5.5.1. Polinom értéke adott pontban...120 5.5.2. Polinomok összege...121 5.5.3. Polinomok szorzata...121 5.5.4. Determináns...122 5.6. Kitűzött feladatok...126 6. RENDEZÉSI ALGORITMUSOK...131 6.1. Bevezetés...131 6.2. Összehasonlításos rendezési módszerek...131 6.2.1. Buborékrendezés (Bubble-sort)...131 6.2.2. Egyszerű felcseréléses rendezés...134 6.2.3. Válogatásos rendezés...135 6.2.4. Minimum/maximum kiválasztásra épülő rendezés...136 6.2.5. Beszúró rendezés...136 6.3. Rendezések lineáris időben...137 6.3.1. Leszámláló rendezés (ládarendezés, Binsort)...138 6.3.2. Számjegyes rendezés (Radix-sort)...138 7. REKURZIÓ...141 7.1. Bevezetés...141 7.2. Közvetlen rekurzió...142 7.3. Megoldott feladatok...145 7.3.1. Egy szó betűinek megfordítása...145 7.3.2. Szavak sorrendjének megfordítása...147 7.3.3. Faktoriális...147 7.3.4. Legnagyobb közös osztó...148 7.3.5. Számjegyösszeg...148 7.3.6. Descartes-szorzat...149 7.3.7. k elemű részhalmazok...151 7.3.8. Konverzió...153 7.3.9. Fibonacci-sorozat (Vigyázat: ellenpélda!)...153 7.4. Rekurzív szerkezetű feladatok...155 7.4.1. A {0, 1, 2} halmaz elemeivel generált sorozatok...155 7.4.2. Az {1, 2,..., n} halmaz minden részhalmaza...156 7.4.3. Partíciók...156 7.4.4. Halmazpartíciók...157 7.4.5. Kamatos kamat...159 7.5. Kitűzött feladatok...160 8. A VISSZALÉPÉSES KERESÉS MÓDSZERE (BACKTRACKING)...161 8.1. Bevezetés...161 8.2. A visszalépéses keresés általános bemutatása...161 8.2.1. Iteratív algoritmus...162 8.2.2. Rekurzív algoritmus...163 8.2.3. 8 királynő a sakktáblán...165 8.2.4. Variációk...168 8.2.5. Zárójelek...171

8 TARTALOMJEGYZÉK 8.2.6. Legrövidebb utak...172 8.2.7. Játékok...173 8.2.8. Szürjektív függvények...174 8.3. A visszalépéses keresés bővítése...175 8.3.1. S pénzösszeg kifizetése...177 8.3.2. Összegkifizetés, minimum számú bankjeggyel...179 8.4. Visszalépéses keresés a síkban...180 8.4.1. Labirintus...180 8.4.2. Fénykép...183 8.4.3. Legnagyobb méretű tárgyak...184 8.5. Kitűzött feladatok...186 9. AZ OSZD MEG ÉS URALKODJ MÓDSZER (DIVIDE ET IMPERA)...191 9.1. Bevezetés...191 9.2. Az oszd meg és uralkodj módszer általános bemutatása...191 9.3. Megoldott feladatok...192 9.3.1. Szorzat...192 9.3.2. Minimumszámolás...193 9.3.3. Hatványozás...194 9.3.4. Bináris keresés...195 9.3.5. Összefésülésen alapuló rendezés (MergeSort)...200 9.3.6. Gyorsrendezés (QuickSort)...201 9.3.7. Hanoi tornyok...205 9.3.8. Úszómedence...207 9.4. Kitűzött feladatok...210 10.MOHÓ ALGORITMUSOK (GREEDY MÓDSZER)...213 10.1. Bevezetés...213 10.2. A mohó algoritmus általános bemutatása...214 10.3. Megoldott feladatok...216 10.3.1. Összeg...216 10.3.2. Az átlagos várakozási idő minimalizálása...216 10.3.3. Buszmegállók...220 10.3.4. Autó bérbeadása...221 10.3.5. Hátizsák...224 10.3.6. Minimális feszítőfák (Kruskal és Prim)...226 10.3.7. Minimális hosszúságú utak (Dijkstra algoritmusa)...230 10.4. Heurisztikus mohó algoritmusok...236 10.4.1. Utazóügynök...236 10.4.2. Gráfszínezés...239 10.4.3. Összegkifizetés legkevesebb számú bankjeggyel...240 10.5. Kitűzött feladatok...241 Algoritmusok listája...249 Szakirodalom...251

Bevezetés A számítógép megjelenése, de főleg erőteljes behatolása a gazdaságba, majdnem minden munkahelyre és az emberek személyes életébe ma már azt jelenti, hogy a számítógéppel megoldható feladatok és alkalmazások egyre változatosabbakká, egyre összetettebbekké és elengedhetetlenül szükségesekké váltak. Amikor egy számítógépet használunk, nemcsak a gép működik, hanem azok a programok is, amelyek biztosítják, ellenőrzik és összehangolják a számítógép működését, és lehetővé teszik azoknak a programoknak a végrehajtását, amelyek közvetlenül fontosak az alkalmazásaink szempontjából. Ebből következik, hogy a távoli jövőben is egészen biztosan egyre több programra lesz szükség a világban. Ez jól hangzik a kezdő programozó számára, de számolnunk kell egy sor sajátos következménnyel. Már ma sem lehet csak úgy összedobálni egy programot, de a jövőben még több szabály, módszer és megszorítás várható, amelyek a csoportmunkát, olvasható programok írását és a könnyű frissítéseket hivatottak biztosítani. A programokat, általában egy megrendelő számára írja a programozó cég, tehát az első legfontosabb cél a megrendelő igényeit kielégíteni. De ahhoz, hogy egy cégnek ez eredményesen sikerüljön, megfelelő tervezési és megvalósítási stratégiát kell követnie. Egy alkalmazás kivitelezéséhez nem elég a programozási környezet ismerete. Ennél fontosabb elsajátítani a feladatok elemzési módszereit, megtanulni kiválogatni a legelőnyösebb eszközöket (programozási nyelvet, illetve környezetet, a környezet könyvtáraiban létező alprogramokat, korábban megírt programrészleteket, saját unitokat stb.), megtalálni a leghatékonyabb algoritmusokat és eredményesen kódolni ezeket. Ennek a jegyzetnek az egyik célja felkészíteni a kezdő programozót arra, hogy a fent felsorolt követelményeknek eleget tehessen. Látni fogjuk, hogy ezek között a legigényesebb tevékenység az algoritmus megtervezése és annak belátása, hogy az valóban helyes és megfelelően hatékony. Ehhez elsősorban gondolkodnunk kell, de a gyakorlat is rendkívül fontos. A jegyzet tehát az algoritmusokkal foglakozik. A hallgató implementálhatja ezeket valamely, már eddig megismert programozási környezetben, illetve, ennek hiányában, ajánljuk a Pascal nyelv elsajátítását. (A jegyzet nem tartalmazza egyetlen programozási nyelv szintaxisát sem.) A kitűzött feladatok megoldása

10 BEVEZETÉS az algoritmus megtervezését és a megfelelő program megvalósítását jelenti. Ezért a jegyzetbe programozásra vonatkozó sajátos tanácsok is bekerültek. Egy adott feladat megoldására lehetséges több, különböző programot írni: valójában k programozó k különböző megoldást fog adni, de ezeknek az alapja sok esetben ugyanaz az algoritmus. De az algoritmusok is különbözhetnek ugyanazon feladat megoldásakor. Ezek lehetnek egyenértékűek, vagyis azonos hatékonyságúak, de lehetnek különbözők a hatékonyság szempontjából is. Ilyenkor mondjuk, hogy egyik algoritmus kisebb bonyolultságú mint a másik. A bonyolultság fogalmának tárgyalása nem célja a jegyzetnek, de a feladatok elemzése és megoldása során elkerülhetetlen a bonyolultság megállapítása, főleg akkor, amikor két vagy több algoritmust össze fogunk hasonlítani. Bemutatásra kerül néhány alapvető kérdés az algoritmusok létezésének, helyességének, futási idejének és optimalitásának bizonyítását illetően. Az algoritmusokat a tervezés során nem szoktuk azonnal egy adott programozási nyelvben írni, hanem valamilyen ábrázolási módszert választunk. E módszerek közül egyesek grafikai eszközöket használnak (például a folyamatábrák), mások leírják vázlatosan az algoritmust (pszeudokód nyelvek). Ezen ábrázolásmódokban egyszerűsítéseket és a programozási nyelveknél kevésbé szigorú szabályokat alkalmazunk. A jegyzetben az algoritmusokat egy egyszerű pszeudokód nyelvben írjuk le, amelynek szintaxisát a 2. fejezetben adjuk meg. A programfejlesztés egyik módja, amelyet ebben a jegyzetben alkalmazunk a strukturált programozás alapszabályaihoz igazodik. A strukturált programozás elemeit, valamint a moduláris programozás előnyeit szintén a 2. fejezetben tárgyaljuk. A fejezet végén megoldott feladatok egyszerűek, a kezdőknek sem okoznak gondot, a kitűzött feladatok pedig alkalmat adnak a gyakorlásra. Algoritmustervezéskor először egy vázlatot készítünk, ezt ellenőrizzük, kiegészítjük, módosítjuk, többször javítgatjuk. Az algoritmust kódolás után is tovább finomítjuk. A lépésenkénti finomítás elvével a 3. fejezetben ismerkedünk meg. Ahhoz, hogy valóban hasznos tagjai lehessünk egy programozó csoportnak, nem elég, hogy értsünk az algoritmusok tervezéséhez és elemzéséhez. Olyan algoritmusokat kell megvalósítanunk, amelyek könnyen olvashatók és amelyek bizonyos mintákhoz (szabályokhoz) igazodnak. Ezeket a mintákat programozási tételek elnevezés alatt a 4. fejezetben mutatjuk be. A programozási tételek egyszerű feladatok hatékony algoritmusai, amelyek részalgoritmusok formájában felhasználhatók későbbi feladataink megoldásaiban. Az 5. fejezetben tulajdonképpen már a programozási gyakorlatra készülünk. Megismerkedünk a feladatok részfeladatokra bontásának következményeként megvalósítandó olyan algoritmusokkal, amelyeket alprogramokkal implementá

BEVEZETÉS 11 lunk és ezeknek az összefűzési módjaival (top-down és bottom-up programozási stílus). A 6. fejezet a legfontosabb rendezési algoritmusokat tárgyalja: az összehasonlításos rendezési módszerek közül a buborékrendezést, az egyszerű felcseréléses rendezést, a válogatásos rendezést, a minimum/maximumkiválasztásra épülő rendezést és a beszúró rendezést fogjuk megismerni. A lineáris rendezések közül bemutatásra kerül a leszámláló rendezés és a számjegyes rendezés. Miután a 7. fejezetben megismerkedünk a rekurzió fogalmával, a 8. fejezet ben elsajátítjuk a visszalépéses keresés (backtracking) technikáját, a 9. fejezetben az oszd meg és uralkodj módszert (divide et impera) tanulmányozzuk, a 10.-ben pedig a mohó algoritmusokat (greedy). A fejezetek végén több megoldott feladatot mutatunk be, és más feladatokat pedig megoldásra ajánlunk. Az algoritmusok tanulmányozása nem ér véget ezzel a jegyzettel. A későbbiekben az adatszerkezetek tanulmányozása vár ránk. Ezeket az adatszerkezeteket sajátos algoritmusokkal dolgozzuk fel. Algoritmusok tervezése és elemzése címmel újabb előadássorozat keretén belül más algoritmusokkal és módszerekkel (például a dinamikus programozás módszerével, a Branch and Bound-dal, Dirichlet skatulya-elvével, véletlenszám generátorra épülő nemdeterminisztikus algoritmusokkal stb.) fogunk találkozni. Ugyanott újabb elemzési módszereket és az algoritmusok helyességének bizonyításait fogjuk elsajátítani. Nem állítom, hogy minden csak úgy igaz, ahogy ebben a jegyzetben le van írva. Várom az olvasók észrevételeit, és előre köszönöm a javaslatokat. Kívánok sikeres tanulást és sok örömöt az algoritmusok szépségeinek felfedezése során! * * * Köszönöm Kása Zoltán és Horia Georgescu tanár urak sok éve tartó megtisztelő barátságát, szakmai tanácsaikat, Buzogány Lászlónak és Kása Zoltánnak a figyelmes szaklektorálást. Köszönöm Takács Andreának a második kiadás előtt végzett pontos és igényes ellenőrző munkáját. Kolozsvár, 2007. augusztus 28. I. K.

12 BEVEZETÉS

1 A SZÁMÍTÓGÉPES FELADATMEGOLDÁS LÉPÉSEI 1.1. A programozói tevékenység A számítógép egy feladatot akkor képes megoldani, ha végrehajtjuk rajta azt a programot, amelyet abból a célból írtunk, hogy a feladatot megoldja. A felhasználó a programon keresztül irányítja a számítógép által elvégzendő lépéseket és biztosítja a feladat automatikus módon való megoldását. Tudvalevő, hogy egy alkalmazás nem egyetlen program megírását jelenti, hanem több személy, többhetes, esetleg többéves munkáját egy teljes programrendszer létrehozására. Ha például egy olyan rendszert kell megvalósítani, amely egy város vízellátását hivatott ellenőrizni és irányítani, a programokba a legapróbb részletekig be kell vinni minden lehetséges részfeladat megoldását úgy, hogy az eredmény a lehető legrövidebb idő alatt megszülessen. De ezt a programrendszert a városban megjelenő új épületek számára állandóan bővíteni kell, más épületek módosulhatnak, illetve eltűnhetnek, tehát az ilyen típusú módosításokat is folyamatosan el kell végezni. A programozók ma már főleg csapatban dolgoznak, így szükségessé vált a programozói tevékenység szabályozása, egy bizonyos sajátos fegyelem megkövetelése, a programozók közti kommunikáció szabványosítása, valamint a megoldandó feladatok szövegeinek megfelelő specifikálása. A programozás történetében az első kísérlet, amely a programozási munka egyszerűsítését tűzte ki céljául a moduláris programozás elveként vált ismertté (1956). Ennek az elvnek az értelmében az eredetileg bonyolult feladatot részfeladatokra bontjuk, és az ezeket megoldó algoritmusokat alprogramokkal kódoljuk. A részfeladatokat megoldó alprogramokat összefűzve, megkapjuk az eredeti feladat megoldását. A következő fontos lépést a strukturált programozás megjelenése jelentette 1972-ben, amikor E. W. Dijkstra olyan algoritmusokat javasolt, amelyekből már

14 1. A SZÁMÍTÓGÉPES FELADATMEGOLDÁS LÉPÉSEI hiányzik a goto utasítás 1. Ezáltal nagymértékben megnőtt a programok olvashatósága, frissíthetősége, sőt könnyebb lett azok karbantartása is. A strukturált programozás elméleti megalapozását folytatta Böhm és Jacopini, akik bebizonyították, hogy bármely algoritmus megvalósítható a három alapstruktúrával, amelyek: a szekvencia, az elágazás (vagy döntés) és az előltesztelő ismeretlen lépésszámú ciklus (iteráció). 1.2. A feladatmegoldás lépései számítógépes környezetben Ha egy bizonyos feladatot számítógéppel szeretnénk megoldani, az ember által elvégzendő lépések a következő módon csoportosíthatók [7]: a) A követelmények és a feladat megfogalmazása A megrendelő leírja a kivitelező számára (sokszor pontatlanul és ellentmondásosan) azt a feladatot, amelyet számítógépes programmal szeretne megoldani a jövőben. A leírás (általában) a kimenetre összpontosít. b) A feladat specifikációja Több beszélgetés szükséges ahhoz, hogy a programozó csoport rendszertervezője pontosan megfogalmazhassa a feladatot (ismernie kell milyen körülmények között, mekkora méretű adatokkal, milyen számítógépen kerül fölhasználásra az elkészítendő program). A következő lépésben a rendszertervezők elemzik a megrendelő követelményeit és lefordítják saját nyelvükre a feladatot, vagyis létrehozzák azt a belső használatra készülő dokumentációt, amely a feladat pontos és helyes specifikációját tartalmazza. Itt már bemeneti és kimeneti adatokról, valamint megszorításokról (a bemeneti adatok és az adatszerkezetek méretéről, az elfogadható legnagyobb futási időről stb.) van szó. A specifikációt ellenőrzi a megrendelő, ellenőrzi a programozó csoport vezetője, de sokszor szükséges, hogy egy, a csoporttól független szakember is elmondja a véleményét. c) Az algoritmus megtervezése (elemzés, modellek és módszerek megállapítása) A specifikáció létrejötte után a csoport tagjai kiválasztják a megfelelő matematikai modelleket, megtervezik az adatszerkezeteket és eldöntik, hogy milyen programozási környezetben milyen módszereket fognak alkalmazni. A módszerek és az adatszerkezetek egymást befolyásolják, ezért gyakran előfordul, hogy több megoldási lehetőség is elemzésre kerül. Az a megoldás lesz a jobb, amely a számítógép erőforrásait (memória és idő) a leghatékonyabban használják. A feladatot részfeladatokra bontják és megtervezik a 1 A goto utasítás hatására a számítógép nem a programban következő utasítást, hanem a goto-ban feltüntetett címkével azonosítottat hajtja végre.

1. A SZÁMÍTÓGÉPES FELADATMEGOLDÁS LÉPÉSEI 15 megoldásokat. A matematikai modellek, az adatszerkezetek és az algoritmusok kiválasztása általában összefonódik. Ekkor alakulnak ki a modulok és a köztük levő kapcsolatok. A tervezés során elkészül egy dokumentáció, amely tartalmazza a megoldás vázát, a választások indoklását. Minderre a kódolás során, valamint a program karbantartásakor lesz szükség. d) Kódolás (az algoritmus implementálása egy programozási nyelvben) Ebben a fázisban az algoritmust átírjuk valamilyen programozási nyelvre, amelyet a feladat jellegének megfelelően gondosan választunk ki. e) Tesztelés (ellenőrzés és érvényesítés, vagyis annak ellenőrzése, hogy a bemeneti és kimeneti adatok megfelelnek-e a specifikációknak) E tevékenység során a programozó különböző tesztadatok esetében tanulmányozza a program működését. Természetesen, arra számít, hogy a program a várt (helyes) adatokat adja, de ezen túlmenően megfigyeli a futási időt, a biztonságos működést stb. A felfedezett hibákat kijavítja, majd újra ellenőrzi az eredményt. Sok esetben a tesztelés beindulhat sokkal hamarabb, egy-egy részfeladat megoldása után. Tulajdonképpen olyan ellenőrzésről van szó, amely nem áll egy különálló fázisból, hanem egy folyamatos tevékenység, amely a tervezés, kódolás és karbantartás során zajlik. Az ellenőrzés lényeges összetevője az úgynevezett érvényesítés. Ezt előbb elvégzi a kivitelező, később a felhasználás során a megrendelő. Megjegyzendő, hogy a megrendelő nem végez ellenőrzéseket, hanem valós adatokkal futtatja a programot és azt várja, hogy a program a megfelelő alakban írja ki az eredményeket. f) A tervezői és a felhasználói dokumentáció elkészítése A dokumentációk a program fontos tartozékai, amelyek a programhoz kapcsolódó fontos információkat tartalmazzák. A fejlesztői dokumentáció leírja, hogyan volt megtervezve a program, a felhasználói dokumentáció elmagyarázza, hogyan kell használni a programot. g) Felhasználás és karbantartás A megrendelő a programot a felhasználás közben valós adatokkal futtatja. Ez természetesen hosszabb ideig zajlik, és előfordulhat, hogy a felhasználás során bizonyos programrészeket a programozónak meg kell változtatnia. 1.3. Alkalmazások minőségi szempontjai Helyesség A program helyes, ha pontosan megoldja a feladatot, megfelel a pontos és helyes specifikációnak.

16 1. A SZÁMÍTÓGÉPES FELADATMEGOLDÁS LÉPÉSEI Megbízhatóság Egy programot megbízhatónak nevezünk, ha helyes eredményt határoz meg, és a specifikációban nem leírt helyzetekben is intelligens módon viselkedik. Karbantarthatóság A karbantarthatóság annak mérőszáma, hogy milyen könnyű a programterméket a specifikáció esetleges változtatásához adaptálni. Egyes felmérések szerint a szoftverköltségek 70%-át a szoftverek karbantartására fordítják! A karbantarthatóság növelése szempontjából a két legfontosabb alapelv: a tervezési egyszerűség és a decentralizáció (minél önállóbb modulok létrehozása). Újrafelhasználhatóság Az újrafelhasználhatóság a szoftvertermékek azon képessége, hogy egészben vagy részben újrafelhasználhatók új alkalmazásokban. Kompatibilitás A kompatibilitás azt mutatja meg, hogy milyen könnyű a szoftvertermékeket egymás között kombinálni. Hordozhatóság A program hordozhatósága arra vonatkozik, hogy menynyire könnyű a programot más géphez, konfigurációhoz, vagy operációs rendszerhez általában más fizikai környezethez igazítani. Hatékonyság A program hatékonysága a futási idővel és a felhasznált memória méretével arányos minél gyorsabb, illetve minél kevesebb memóriát használ, annál hatékonyabb. Barátságosság A program emberközelisége, barátságossága a felhasználó számára rendkívül fontos: ez megköveteli, hogy a bemenet logikus és egyszerű, az eredmények formája áttekinthető legyen. Tesztelhetőség A tesztelhetőség, a program karbantartói, fejlesztői számára fontos.

2 AZ ALGORITMUSOK ÁBRÁZOLÁSA 2.1. Algoritmusok Mivel a számítástechnika egyik bűvös szava az algoritmus, lássuk hogyan is alakult ki ez a szó. D. E. Knuth így vélekedik a szó eredetéről: Az algoritmus szó már önmagában is nagyon érdekes. Úgy tűnhet egy pillanatig, hogy a logaritmus szót akarta valaki leírni, de nem sikerült neki, mert összezagyválta az első négy betűt. A matematikatörténészek azt állítják, hogy az algoritmus szó Abu-Ja far Mohammed ibn Mura al-kvarîzmi (780 k. 850 k.) arab matematikus nevének, al-kvarîzmi latinos elferdítéséből származik. 2.1.1. Az algoritmus fogalma A mindennapi életben gyakran kerülünk olyan helyzetbe, amikor meglévő ismereteink alapján nem tudjuk azonnal megmondani, hogy elérhető-e a kitűzött célunk, és ha igen, hogyan. A megoldás két dolgot feltételez: az eredmény milyenségének, azaz elvárásainknak pontos ismeretét; annak a folyamatnak a tervét, amely az eredmény eléréséhez vezet. A cél elérése érdekében megtervezzük az elvégzendő cselekvések sorozatát, vagyis megtervezzük az algoritmust, amely a kívánt eredményhez vezet. Olyan problémamegoldó eljárást (algoritmust) kell kidolgoznunk, amely véges számú lépésben befejeződik, és a rendelkezésre álló (bemeneti) adatokból előállítja az úgynevezett eredményt (kimeneti adatokat), vagyis megoldja a feladatot. [18] Azt gondolhatnánk, hogy mi sem egyszerűbb, mint a feladat megoldását a számítógépre bízni. Igen ám, de a számítógép csak azt tudja elvégezni, amit a felhasználó megnevezett! Ezért, amikor a számítógépnek kell megmondanunk, hogy mit csináljon, akkor egyértelmű leírást kell adnunk úgy, hogy gépünk számára is követhető legyen az elképzelésünk.

18 2. AZ ALGORITMUSOK ÁBRÁZOLÁSA Az algoritmust úgy is definiálhatjuk, mint egy adott feladatkör megoldására kidolgozott olyan eljárást, amely utasításszerűen előre megadott lépések sorozatából áll. De ahhoz, hogy az algoritmus fogalmát tisztázhassuk, még több tulajdonságra is oda kell figyelnünk. Mielőtt sorra vennénk az algoritmusok főbb jellemzőit, próbáljuk megadni az algoritmus pontosabb leírását. Napjainkban algoritmus alatt egy véges, bizonyos sorrendben megadott egyértelmű műveletsort értünk, amelyek mechanikusan elvégezhetők (anélkül, hogy az ember arra szorulna, hogy saját maga döntéseket hozzon), és amelyek a rendelkezésre álló adatokból új adatokat hoznak létre, vagy más formában vezetnek a kívánt eredményhez. Az algoritmusokat valamilyen feladat megoldásának céljából tervezzük, majd valamilyen programozási nyelv segítségével kódoljuk, hogy számítógépen végrehajthassuk. Mielőtt számba vennénk az algoritmusok tulajdonságait, hangsúlyozzuk, hogy a számítógépes világ ismer szekvenciális és párhuzamos algoritmusokat. Egy szekvenciális algoritmus az utasításait egymás után hajtja végre, míg egy párhuzamos algoritmus esetében több utasítás is végrehajtódik ugyanabban a pillanatban, mivel ezeket több processzor végzi párhuzamosan. Valamely szekvenciális algoritmus akkor helyes, ha eleget tesz az alábbi követelményeknek: a) elvégezhető vagyis az ember is képes eljutni az eredményhez, papírral és ceruzával a kezében követve az algoritmusban leírt műveletek hatását; b) meghatározott azaz, bármelyik pillanatban tudjuk, hogy éppen mi fog történni (ez csak a determinisztikus algoritmusokra érvényes); c) általános egy adott feladatkör megoldására képes; d) véges az algoritmus véges számú lépésben vezet eredményre, bármilyen kezdeti értékekből kiindulva. Ezekhez hozzátesszük, hogy egy algoritmust a helyességén kívül a következő tulajdonságok is jellemezhetik: e) világos az algoritmus leírása pontos, érthető, követhető; f) hatékony egy bizonyos feladatot több algoritmussal is megoldhatunk, de ezek közül mindig megkeressük azt, amely a legkevésbé veszi igénybe a számítógép erőforrásait, vagyis nem terheli fölösleges műveletek elvégzésével, illetve fölösleges adatok tárolásával; azt mondjuk, hogy ezek az algoritmusok hatékonyak, optimálisak, vagyis a bonyolultságuk a lehető legkisebb.

2. AZ ALGORITMUSOK ÁBRÁZOLÁSA 19 Az algoritmusok helyességének bizonyítását később fogjuk alaposabban tanulmányozni. Egyelőre marad a lehetőség, miszerint az algoritmusokat teszteljük, ellenőrizzük. Egy algoritmus kezdeti értékeket igényel, ezekből származtatja az eredményt. A kezdeti értékeket bemeneti (bemenő) adatoknak nevezzük. Ide sorolhatjuk azokat a konstans értékeket is, amelyekkel inicializálunk. Az algoritmus által szolgáltatott adatokat (eredményt) kimeneti (kimenő) adatoknak nevezzük. Mindaz amit az algoritmus elvégez, a funkciójaként nevezhető meg. 2.1.2. Az algoritmusok leírásánál használt elemek A. Adatok Az adatokat típusuk szerint a következőképpen osztályozhatjuk: a) A numerikus adatok csoportjába tartoznak az egész típusú adatok, azaz egész számok, valamint a valós típusú adatok, azaz a tizedes számok. A valós típusú adatok jelölésekor tizedesvessző helyett tizedespontot használunk (például 3,47 helyett 3.47-et). b) A logikai adatok mindössze két értéket vehetnek fel: a logikai igaz (true), valamint a logikai hamis (false) értékeket. c) A karakterláncok egyszeres idézőjelek (aposztrófok) közé zárt karaktersort jelentenek (például 'ez egy szoveg'). B. Állandók (konstansok) Algoritmusok írásakor numerikus, logikai és karakterlánc típusú állandókat használhatunk. Ezek nem változtatják értéküket az algoritmusban. C. Változók Az algoritmusok leírásakor használt olyan elemeket, amelyeknek értéke az algoritmus végrehajtása során időben módosulhat, változóknak nevezzük. Amikor az algoritmus alapján programot írunk, amelyet a továbbiakban számítógépünkön szeretnénk futtatni, akkor minden változónak helyet kell foglalnunk a memóriában. A lefoglalt hely mérete attól függ, hogy milyen típusú 2 adatot fogunk az illető változóban tárolni. Azok a változók, amelyek még nem kaptak értéket, inicializálatlanok (nincs kezdőértékük). 2 Egy típus meghatározza azoknak az értékeknek a halmazát, amelyből értékeket kaphat a változó, valamint azokat a műveleteket, amelyeket ezekkel az értékekkel elvégezhetünk.

20 2. AZ ALGORITMUSOK ÁBRÁZOLÁSA Összefoglalva: minden változónak van neve, attribútumhalmaza (például típus), helye (címe) a memóriában, értéke. A változók típusa, a konstansokéhoz hasonlóan lehet numerikus, logikai és karakterlánc típusú. Ezeket a típusokat standard típusoknak nevezzük. Mellettük még végtelen sok típust definiálhat maga a programozó. D. Kifejezések A kifejezés egy számítás jelölése: előírja valamely érték kiszámításának módját. A kifejezés műveletekből és operandusokból áll. Az operandusok lehetnek konstansok, változók vagy függvényhívások (a függvénykifejezés valamely függvény kiértékeléséről gondoskodik). A kifejezés kiértékelése a megszokott matematikai szabályoknak megfelelően, az ismert precedencia figyelembevételével történik. Azonos prioritású műveletek esetében a kifejezés kiértékelését balról jobbra haladva végezzük. Az algoritmusok leírásakor numerikus, logikai és karakterlánc típusú kifejezéseket használhatunk. D1. Egész típusú kifejezések Az egész típusú kifejezések operandusai egész típusúak. Az egész típusú kifejezésekben a következő műveleteket használhatjuk: Művelet jele Jelentése + összeadás kivonás * szorzás [a/b] egész számok osztásának hányadosa maradék[a/b] egész számok osztási maradéka D2. Valós típusú kifejezések A valós típusú kifejezések operandusai valós típusú változók vagy állandók, de ezek közé kerülhetnek egész típusúak is. A valós típusú kifejezésekben a következő műveleteket használhatjuk: Művelet jele Jelentése + összeadás kivonás * szorzás / osztás

2. AZ ALGORITMUSOK ÁBRÁZOLÁSA 21 Megjegyzés A kifejezés típusát, a kifejezésben szereplő operandusok típusa, valamint a műveletek határozzák meg! D3. Logikai kifejezések A logikai kifejezések operandusai logikai típusúak. A logikai kifejezések leírásában a következő műveleteket használhatjuk: relációs műveletek: <, >,,, =, ; logikai műveletek: vagy, és, nem (vagyis az eredeti állítás tagadása, ellenkezője), xor (kizárólagos vagy); a logikai műveletek eredményeit a következő táblázatok tartalmazzák: o I H an I H no I H xo I H r d t r I I I I I H H I I H I H I H H H H H I H Ha egy logikai kifejezés több részkifejezésből áll, ezeket zárójelek közé tesszük, mivel a logikai műveleteknek elsőbbségük van. A leghamarabb a nem (not) hajtódik végre, utána az és (and), végül a vagy (or). A relációs műveletek az aritmetikai kifejezések kiértékelése után kerülnek sorra. D4. Karakterlánc típusú kifejezések A karakterlánc típusú kifejezések operandusai karakterláncok. Ha a egy karakterlánc típusú változó és értéke például ' Ez egy ', akkor például az a + 'barack' kifejezés értéke ' Ez egy barack' lesz. A karakterláncok szerepelhetnek relációs kifejezésekben, ilyenkor a lexikográfikus sorrendnek megfelelően történik az összehasonlítás: Legyen a és b két karakterlánc típusú változó: a = 'barack', b = 'dió', ebben az esetben a < b. Az a = b relációs kifejezés értéke hamis, az a b értéke igaz. E. Műveletek Az algoritmusok leírásakor az alábbi műveleteket használhatjuk: ki/bemeneti műveletek; értékadás; döntéshozatal.

22 2. AZ ALGORITMUSOK ÁBRÁZOLÁSA E1. Ki/bemeneti műveletek A bemeneti művelet szerepe bekérni a szükséges bemeneti adatokat. Ezeket billentyűzetről vagy állományokból olvashatjuk be. A kimeneti művelet szerepe a feldolgozott adatokat, eredményeket megjeleníteni. Ez a kiírás történhet a képernyőre, papírra vagy valamilyen állományba. E2. Értékadás Az értékadó művelet a (vagy :=) műveleti jel bal oldalán található változóhoz hozzárendeli a jobb oldalon lévő kifejezés értékét. Példa Az a 10 értékadás hatására a elveszti (esetleges) régi értékét, mivel az értékadás végrehajtása következtében az értéke 10 lesz. Az a a + 1 értékadás hatására a új értéke a régi értékénél 1-gyel nagyobb lesz. E3. Döntéshozatal A döntéshozó művelet lényege, hogy adott feltételek teljesülésekor egy bizonyos műveletsort kell elvégeznünk, egyébként egy másik műveletsort. Ha valamelyik ág üres, akkor természetesen azon az ágon nem történik semmi. F. Adatszerkezetek 3 Adatszerkezet alatt az adatok olyan csoportosulását értjük, amelyben pontos szabályok szerint szervezzük a feldolgozandó adatokat. Egy adattípuson belül azonos tulajdonságú értékeket foglalunk egybe, amelyekhez hozzárendeljük az elvégezhető műveleteket. Megkülönböztetünk: egyszerű adattípusokat (például az egész típusú számot nem tekintjük számjegyek sorozataként). összetett adattípusokat (az értékek elemekre bonthatók, az elemek egy adott szerkezetnek megfelelően csoportosulnak). Így az adatszerkezet egy olyan adattípus, amelynek az értékei felbonthatók adatelemek értékeinek halmazára, amelyeknek típusa lehet egyszerű vagy összetett. Az adatszerkezeten belül ismerjük az elemek közti kapcsolatot (szerkezetet). 3 Az adatszerkezeteket egy másik tantárgy keretén belül fogjuk alaposabban tanulmányozni.

2. AZ ALGORITMUSOK ÁBRÁZOLÁSA 23 Például az Integer egy egész adattípus, amelyet a Pascal programozási nyelv ismer. Ha több egész számot szeretnénk egy adatkent kezelni, akkor egy sorozatot képezünk belőlük. Ekkor a sorozat egy adatszerkezet (vektor), amelynek az elemei az egész számok. Az elemek közti kapcsolat az, hogy egymás után következnek. Műveletek: elemek lekérdezése a sorszámuk (indexük) segítségével, értékadás stb. 2.2. Algoritmusok ábrázolása folyamatábrák és pszeudokód nyelvek segítségével Az algoritmusokat többféleképpen lehet ábrázolni. Ismeretesek a folyamatábrák, a pszeudokód nyelv, különböző típusú diagrammok, de a hétköznap használt nyelv is előfordul. Mivel ez utóbbi nehézkes lehet, hosszú és nem eléggé szabatos, az első két ábrázolással fogunk gyakrabban találkozni. A folyamatábra az algoritmusok leírásának egyik legegyszerűbb és legszemléletesebb módja. A folyamatábra grafikus ábrázolásmód, amelynek segítségével nem csupán az egyes műveleteket, hanem ezek elvégzésének sorrendjét és összefüggését is feltüntetjük. Folyamatábrák készítésekor az egyes műveleteket blokknak nevezett ábrák segítségével jelöljük, amelyeknek alakja a művelet típusára, tartalma pedig a művelet leírására utal. A folyamatábra hasonlít egy gráfhoz, ahol a lerajzolt nyilak irányításának megfelelően egy kiinduló helyzetből eljutunk az algoritmus végére úgy, hogy menet közben feltüntetjük az elvégzendő műveleteket. Az alapműveleteknek különböző síkidomok felelnek meg, ezeknek a belsejébe írjuk a műveleteket. a) indító- és záróblokk START STOP b) be és kimeneti műveletek Be v Ki v c) értékadás előbb kiszámítódik a kifejezés értéke; a kiszámított érték átadódik a változónak (bemásolódik a változó számára lefoglalt memóriarekeszbe); ha a változónak volt előző értéke, az változó kifejezés

24 2. AZ ALGORITMUSOK ÁBRÁZOLÁSA az aktuális értékadás következtében elvész, mivel felülíródik az új értékkel. d) alprogram (algoritmus) hívása feltételezzük, hogy létezik az ELJÁRÁS nevű algoritmus, vagy legalább a funkcióját ismerjük; az ELJÁRÁS(L) blokk egy műveletsort jelöl, amelyet egy különálló folyamatábrával írunk le. E folyamatábra indítóblokkja a műveletsor nevét és az L paraméterlistát, míg záróblokkja az EXIT szót tartalmazza. ELJÁRÁS(L) e) elágazás (döntés) feltételezzük, hogy a feltétel egy logikai kifejezés, amely vagy igaz, vagy hamis; az algoritmus végrehajtását a feltételtől függően vagy a jobb vagy a bal ágon folytatjuk tovább HAMIS feltétel IGAZ Példa Legyen egy természetes szám. Ábrázoljuk folyamatábrával azt az algoritmust, amely megvizsgálja, hogy a szám palindrom szám-e vagy sem. Egy számot palindromszámnak (vagy tükörszámnak) hívunk, ha egyenlő a fordított -jával, vagyis azzal a számmal, amelyet a szám számjegyei fordított sorrendben alkotnak. Megoldás A számot számjegyekre bontjuk, és a bontással párhuzamosan felépítjük az új számot. Az új szám generálását a Horner-séma néven ismert módszer segítségével végezzük (a ciklusban újszám újszám 10 + számjegy). Mivel az algoritmus a számjegyeket úgy határozza meg, hogy ismételten osztja az eredeti számot 10- zel, az algoritmus végén az eredeti szám értéke 0. De nekünk szükségünk van az eredeti értékre, hogy összehasonlíthassuk a kapott új számmal. Ezért a beolvasott számról a feldolgozás előtt készítünk egy másolatot. A feladatot megoldó algoritmus folyamatábrája ekkor a következőképpen alakul:

2. AZ ALGORITMUSOK ÁBRÁZOLÁSA 25 START Be szám másolat szám újszám 0 szám > 0 IGAZ számjegy maradék[szám/10] HAMIS újszám újszám*10+számjegy szám [szám/10] HAMIS másolat= újszám IGAZ Ki 'Nem' Ki 'Igen' STOP Annak ellenére, hogy a folyamatábrák segítségével az algoritmusok szemléletesen és viszonylag egyszerűen írhatók le, a gyakorlatban ezek használata nehézkesnek bizonyult, egyrészt, mert bonyolultabb feladatok esetében a folya matábrák áttekinthetetlenekké válhatnak, másrészt pedig a grafikus ábrázolás önmagában is sok kellemetlenséget okozhat. Arról ne is beszéljünk, hogy itt megengedett a goto típusú átirányítás, ami végképp megnehezíti az algoritmus olvasását. A folyamatábrák helyett használhatjuk az úgynevezett pszeudokódot, amely az elemi struktúrákat írja le egyszerű utasítások formájában. A pszeudokód nyelv sokban hasonlít a programozási nyelvekhez, emiatt a pszeudókodban leírt algoritmus nagyon könnyen átírható bármely programozási nyelvre.

26 2. AZ ALGORITMUSOK ÁBRÁZOLÁSA Feltevődik a kérdés: akkor miért nem írjuk algoritmusainkat egyenesen valamelyik programozási nyelven? Elsősorban azért nem, mert a pszeudokód leírásmód nem annyira kötött, mint egy programozási nyelv. Másodsorban pedig azért nem, mert a pszeudokódban leírt algoritmus éppen az imént említett rugalmasság miatt bármely programozó számára érthető, általános, nem tartalmazza egy programozási nyelv sajátosságait, és így nemcsak az illető nyelvet ismerő programozók fogják megérteni. A pszeudokódok többfélék lehetnek. Bárki megalkothatja saját pszeudokódját az elemi programozási struktúrák ismeretében. 2.3. A strukturált programozás alapelvei A programozók és a programozást oktatók nagy gondja volt a fegyelmezetlen, minden szabálytól, megkötéstől mentes programozói stílus. Nehézzé, néha lehetetlenné vált a karbantartás. Ezt elhárítandó, N. Wirth kidolgozta a lépésenkénti finomítás (stepwise refinement) elvét. De ez nem bizonyult elegendőnek. A strukturált programozást E. W. Dijkstra és C. A. R. Hoare vezették be 1965-ben. Olyan algoritmustervezési szabályokról van szó, amelyeknek lényege abban áll, hogy olyan algoritmusokat írunk, amelyek csak az elfogadott struktúrákat tartalmazzák. Lényeges észrevenni, hogy kizárták a goto utasítást a felhasználható utasítások közül, ezáltal az algoritmusok olvashatóbbakká, könnyen beláthatóakká váltak és így eredményesebb programozói teljesítményekhez vezettek. A strukturált programozás alapelve szerint az algoritmusok leírására néhány alapstruktúrát (elemi struktúrát) használunk, melyeknek egyetlen bemenete és egyetlen kimenete van. A kitűzött feladatot részfeladatokra bontjuk, majd e részfeladatok megoldásával jutunk el az eredeti feladat megoldásához. Ily módon bármely algoritmus alapstruktúrák lineáris szekvenciájaként tekinthető. Böhm és Jacopini tétele kimondja, hogy bármely algoritmus megvalósítható a három alapstruktúra segítségével: lineáris struktúrával, elágazással és Amíg típusú ismétlő struktúrával. Strukturált algoritmusok írásakor a következő alapstruktúrákat használhatjuk: a) lineáris struktúra valamely művelet feltétel nélküli elvégzését jelenti; b) elágazási (alternatív) struktúra lehetővé teszi, hogy valamely műveletet csak adott feltételek teljesülésekor végezzünk el; c) ismétlő struktúra (ciklus) adott műveletsor véges számszor történő ismételt elvégzése.

2. AZ ALGORITMUSOK ÁBRÁZOLÁSA 27 Az elemi struktúrák használata megkönnyíti az algoritmusírást, ugyanakkor a már kész algoritmus érthetőbb, áttekinthetőbb lesz. 2.3.1. Lineáris struktúrák A lineáris struktúrák a következők: indítóblokk (START); záróblokk (STOP); ki- és bemeneti műveletek; értékadás; az ELJÁRÁS blokk hívása (az ELJÁRÁS blokkhoz tartozó struktúrák nem feltétlenül lineárisak). Lineáris struktúrának tekintjük továbbá a fentiek bármilyen szekvenciáját is. 2.3.2. Elágazási struktúrák Az elágazás a döntéshozó művelet megfelelője, amelyben a feltétel egy logikai kifejezés, amely állhat több részkifejezésből. Ha a feltétel teljesül, akkor a q műveletsort végezzük el, különben a p-t, ahol a q és p tetszőleges számú, bármilyen típusú struktúrákból állhat. p HAMIS feltétel IGAZ q Ha a p vagy a q műveletsor hiányzik, ajánlott úgy megfogalmazni a feltételt, hogy a HAMIS ág váljon üressé. A későbbiekben meg fogunk ismerkedni egy olyan elágazási struktúrával is, amely egyetlen feltétel kiértékelése következtében kettőnél több felé ágaztatja az algoritmust. Példa Olvassunk be egy évszámot (1000 évszám 3000). Döntsük el, hogy az adott év szökőév-e vagy sem! Megoldás Egy szökőév osztható 4-gyel és nem osztható 100-zal, vagy osztható 400-zal.

28 2. AZ ALGORITMUSOK ÁBRÁZOLÁSA START Be évszám HAMIS maradék[évszám/4]=0 és maradék[évszám/100] 0 vagy maradék[évszám/400]=0 IGAZ Ki 'Nem' Ki 'Szökőév' STOP 2.3.3. Ismétlő struktúrák Ha egy adott műveletsort többször is meg kell ismételnünk, ismétlő struktúrát vagy más néven ciklust használunk. A ciklusnak tartalmaznia kell egy feltételt, amely lehetővé teszi a ciklusból való kilépést. A ciklusokat három csoportba soroljuk: a) elöltesztelő ciklus (Amíg típusú struktúra); b) hátultesztelő ciklus (Ismételd típusú struktúra); c) ismert számú ismétlés (Minden típusú struktúra). A továbbiakban e három típust egyenként ismertetjük. a) Elöltesztelő ciklus (Amíg típusú struktúra) Amíg a feltétel értéke igaz, ismételjük a p műveletsort. Amint a feltétel értéke hamissá válik, kilépünk a ciklusból. A p műveletsorban kötelezően lennie kell egy olyan műveletnek, amely megváltoztatja a feltétel logikai értékét, lehetővé téve a ciklusból való kilépést. Előfordulhat, hogy a feltétel értéke már a ciklusba lépés előtt hamis. Ebben az esetben a p műveletsort egyszer sem végezzük el! HAMIS feltétel IGAZ p

2. AZ ALGORITMUSOK ÁBRÁZOLÁSA 29 Példa Olvassunk be több egész számot. A számok beolvasása befejeződik, amikor a beolvasott szám értéke 0. Számítsuk ki az összegüket! Az összeget 0 kezdőértékkel látjuk el. Mivel a számok számát nem ismerjük, sőt az is előfordulhat, hogy az első beolvasott szám értéke 0, ismeretlen számú, elöltesztelő ciklust alkalmazunk. START Be szám összeg 0 szám 0 IGAZ összeg összeg + szám HAMIS Be szám Ki összeg STOP b) Hátultesztelő ciklus (Ismételd típusú struktúra) A p műveletsort addig ismételjük, ameddig a feltétel értéke igazzá nem válik. (Kilépünk amikor a feltétel értéke igaz.) A p műveletsorban szükség van egy olyan műveletre, amely megváltoztatja a feltétel logikai értékét és lehetővé teszi a ciklusból való kilépést. A feltétel értékétől függetlenül a p műveletsort legalább egyszer elvégezzük! IGAZ p feltétel HAMIS Példa Adva van egy pozitív egész szám. Írjuk ki számjegyeinek számát! Megoldás A szám számjegyeinek számát a 10-zel való ismételt egész osztások száma adja meg, amelyeket addig végzünk, amíg a szám 0-vá nem válik. Mivel az eredeti számról tudjuk, hogy 0-tól különbözik, de nem tudjuk, hány számjegye van, a feldolgozást hátultesztelő ismeretlen lépésszámú ciklussal végezzük. Ha az adott szám 0 is lehetett volna, az eredmény akkor is 1, de ebben az esetben egyszer sem kellett volna osztani a számot, tehát elöltesztelő ciklust alkalmaztunk volna.

30 2. AZ ALGORITMUSOK ÁBRÁZOLÁSA START Be szám sz 0 szám [szám/10] sz sz + 1 szám = 0 HAMIS IGAZ Ki sz STOP Feladat Próbáljunk folyamatábrát rajzolni egy elöltesztelő ciklussal megoldott feladat, hátultesztelő ciklussal történő megoldására. c) Ismert számú ismétlés (Minden típusú struktúra) Az Amíg és az Ismételd struktúrák esetében nem tudhatjuk pontosan, hányszor fog ismétlődni a p műveletsor. Ha ismerjük a végrehajtások számát, az előbb bemutatott, módosított elöltesztelő ismétlő struktúrát használhatjuk, amelyben egy úgynevezett ciklusszámláló segítségével ellenőrizzük a műveletsor ismétléseinek számát. Ezt az ismétlő struktúrát Minden típusú struktúrának nevezzük. A p műveletsort addig ismételjük, ameddig az i sorszámozott típusú változó értéke kisebb vagy egyenlő mint az u utolsó megengedett érték (az i első értéke az e kezdőérték). Az i változó a ciklus minden lépésében megváltoztatja értékét. A lépés lehet pozitív vagy negatív egész szám. i e IGAZ i u p HAMIS i i + lépés

2. AZ ALGORITMUSOK ÁBRÁZOLÁSA 31 Különböző programozási nyelvekben a Minden típusú struktúra különbözőképpen van megvalósítva. Példa Számítsuk ki az első n (2 n 20) természetes szám összegét! Megoldás A feladat megoldására Minden típusú struktúrát használunk. A ciklusváltozót i-vel jelöljük, és értékei a ciklus folyamán 1-től n-ig változnak, azaz n darab számot fogunk a ciklusban feldolgozni. Az n értékét a felhasználótól kérjük be. Jelen (és a legtöbb) esetben a lépésszámlálót 1-gyel növeljük. A ciklus által biztosított i ciklusváltozót így nyugodtan felhasználhatjuk az összeg kiszámítására, amelyet az összeg változóban tárolunk. A feladat megoldását a következő folyamatábra szemlélteti. Megjegyzés Látható, hogy az ábra igazán szemléletes, de képzeljünk el egy ennél mondjuk 5-ször bonyolultabb algoritmust. Hogyan ábrázolnánk azt egy ilyen méretű lapon? A továbbiakban mindenkinek az algoritmusok pszeudokóddal történő leírását javasoljuk. START Be n összeg 0 i 1 i n IGAZ HAMIS összeg összeg + i i i + 1 Ki összeg STOP

32 2. AZ ALGORITMUSOK ÁBRÁZOLÁSA 2.3.4. Az alapstruktúrák jelölése pszeudokódban a) A pszeudokódban leírt algoritmus első utasítása: Algoritmus Neve: b) Lineáris struktúrák ábrázolása pszeudokód nyelvben: Struktúra neve Bemeneti struktúra Kimeneti struktúra Értékadó művelet Eljáráshívás Jelölés Be: változólista Ki: változólista változónév kifejezés eljárásnév(paraméterlista) c) Elágazási struktúrák ábrázolása pszeudokód nyelvben: Ha-akkor-különben típusú struktúra: Ha feltétel akkor utasítás(ok)1 különben utasítás(ok)2 Ha az elágazási struktúrából hiányzik a különben ág, akkor Ha-akkor típusú struktúránk van: Ha feltétel akkor utasítás(ok) Példa Határozzuk meg és írjuk ki adott valós szám abszolút értékét! Elemzés Matematikából tudjuk, hogy valamely szám abszolút értéke: x, ha x 0 x x, ha x 0. Beolvassuk az x valós számot. Ha a szám pozitív, akkor az abszolút érték maga a szám lesz, egyébként az abszolút érték maga a szám, de megváltoztatott előjellel. Algoritmus Abszolút_érték(x,mod): Ha x 0 akkor { bemeneti adat: x, kimeneti adat: mod } mod x különben mod -x

2. AZ ALGORITMUSOK ÁBRÁZOLÁSA 33 Megjegyzés Ha az x változó eredeti értékére a továbbiakban nincs szükségünk, elegánsabb megoldást kapunk, ha nem használunk külön változót az abszolút érték tárolására! Egyébként a megoldás hátránya lehet, hogy módosul az x értéke! Algoritmus Abszolút_érték_másként(x): Ha x < 0 akkor { bemeneti és kimeneti adat: x } x -x d) Ismétlő struktúrák ábrázolása pszeudokód nyelvben: Amíg típusú struktúra ábrázolása: Amíg feltétel végezd el: utasítás(ok) vége(amíg) Példa Számítsuk ki két természetes szám egész hányadosát ismételt kivonásokkal! Algoritmus Osztás(a,b,hányados): hányados 0 { bemeneti adatok: a, b, kimeneti adat: hányados } Amíg a b végezd el: hányados hányados + 1 a a - b vége(amíg) Ismételd típusú struktúra ábrázolása: Ismételd utasítás(ok) Ameddig feltétel Példa Számítsuk ki két természetes szám legnagyobb közös osztóját! Megoldás Alkalmazzuk Eukleidész algoritmusát. Kiszámítjuk a két szám osztási maradékát. Ha ez nem 0, ismételten kiszámítjuk az aktuális osztó és az aktuális maradék egész osztási maradékát. Az algoritmus véget ér, amikor az aktuális maradék értéke 0. 4 Algoritmus Eukleidész(a,b,lnko): Ismételd { bemeneti adatok: a, b, kimeneti adat: lnko } r maradék[a/b] { kiszámítjuk az aktuális maradékot } a b { az osztandót felülírjuk az osztóval } b r { az osztót felülírjuk a maradékkal } ameddig r = 0 { amikor a maradék 0, véget ér az algoritmus } lnko a { lnko egyenlő az utolsó osztó értékével } 4 Eukleidész algoritmusára visszatérünk a jegyzet során többször is.

34 2. AZ ALGORITMUSOK ÁBRÁZOLÁSA Minden típusú struktúra ábrázolása: Minden i = e, u, lépés végezd el: utasítás(ok) Példa Számoljuk meg n beolvasott szám közül a páros számokat! Megoldás Tekintsük az alábbi algoritmust! Algoritmus Páros(n,db): db 0 { bemeneti adat: n és a számok, kimeneti adat: db, a páros számok száma } Minden i=1,n végezd el: Be: szám Ha szám páros akkor db db + 1 e) A pszeudokódban leírt algoritmus utolsó utasítása: Megjegyzés Megjegyezzük, hogy az algoritmus és a struktúrák zárását jelölhetnénk egyszerűen a vége sorral, de ha a zárójelben feltüntetjük a struktúrát megnevező szót is (ha, amíg stb.), világosabb lesz az algoritmus leírása, hiszen így jelezzük azt is, hogy minek van vége. Mielőtt zárnánk a jegyzetben alkalmazott pszeudokód nyelvvel való ismerkedést, lássuk a folyamatábrák bemutatása után tárgyalt feladatot megoldó algoritmus ábrázolását pszeudokóddal. (A feladat megoldásában eldöntjük egy adott számról, hogy palindromszáme vagy sem.) Algoritmus Palindrom(szám,válasz): másolat szám { bemeneti adat: szám, kimeneti adat: válasz } újszám 0 Amíg szám > 0 végezd el: számjegy maradék[szám/10] újszám újszám*10 + számjegy szám [szám/10] vége(amíg) válasz újszám = másolat { ha újszám = másolat, akkor válasz értéke igaz } { ha újszám másolat, akkor válasz értéke hamis }

2. AZ ALGORITMUSOK ÁBRÁZOLÁSA 35 2.3.5. Egyszerű alapszabályok A változók jelentését alaposan ismernünk kell! Adjunk minden változónak beszédes azonosítót! Ne használjunk inicializálatlan (kezdőérték nélküli) változókat! Ne használjunk több változót a szükségesnél, mert ez növelheti az algoritmus alapján implementált program memóriaigényét. Az algoritmus utasításait mindig a logikai felépítésnek megfelelően indentáljuk (igazítsuk) úgy, hogy abból mindig egyértelműen kitűnjön, melyik rész, melyik másik résznek az alárendeltje (melyik blokk alá tartozik). Írjunk optimális algoritmusokat! (Egy algoritmus optimalitása nem a kód hosszától, hanem annak hatékonyságától, azaz futási idejétől és erőforrásigényétől függ.) Amennyiben lehetséges írjunk általános algoritmusokat, amelyek más programozási környezetben is különösebb átalakítás nélkül felhasználhatók. Az algoritmusnak minden bemenetre valamilyen kimenetet (eredményt vagy hibaüzenetet) kell szolgáltatnia. A megoldandó feladatot teljes egészében elemezzük! Amíg lehet, a feladatot bontsuk részfeladatokra, az algoritmust pedig részalgoritmusokra (alprogramokra)! Ha a Ha struktúrában egy ág hiányzik, ez legyen a különben! Az egymásba ágyazott Ha struktúrák következzenek a megvalósulásuk valószínűsége szerinti csökkenő sorrendben! A Minden típusú struktúrában ne módosítsuk a ciklusváltozót, és a kezdő-, illetve a végsőértéket sem! Ha az algoritmus tervezésekor ismerjük a programozási környezetet, amelyben ezt kódolni fogjuk, kihasználhatjuk a programozási környezet és a nyelv lehetőségeit is, de ne essünk túlzásba, mivel így az algoritmusunk veszít az általánosságából! 2.4. A feladatok számítógépes megoldásához fűződő általános kérdések A programozótól azt várják el, hogy megvalósítson egy algoritmust, amely megold egy adott feladatot (a megoldás lehet közelítő is, ha ez fel van tüntetve). A megoldhatóság, első megközelítésre, azt jelenti, hogy létezik egy algoritmus, amelynek megfelel egy számítógépes program, amelyet, ha elegendő ideig fut