Programozási tételek és alkalmazásaik

Hasonló dokumentumok
Térinformatikai algoritmusok Elemi algoritmusok

Térinformatikai algoritmusok Elemi algoritmusok

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.

Bevezetés az informatikába

PROGRAMOZÁS tantárgy. Gregorics Tibor egyetemi docens ELTE Informatikai Kar

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

Programozási Módszertan definíciók, stb.

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

Összetett programozási tételek Rendezések Keresések PT egymásra építése. 10. előadás. Programozás-elmélet. Programozás-elmélet 10.

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

Programozási segédlet

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

Alkalmazott modul: Programozás. Programozási tételek, rendezések. Programozási tételek Algoritmusok és programozási tételek

Java programozási nyelv

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

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

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

Programozási tételek. Dr. Iványi Péter

Általános algoritmustervezési módszerek

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

Programozás Minta programterv a 1. házi feladathoz 1.

Maximum kiválasztás tömbben

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

ELEMI PROGRAMOZÁSI TÉTELEK

Véletlen sorozatok ellenőrzésének módszerei. dolgozat

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

5. előadás. Programozás-elmélet. Programozás-elmélet 5. előadás

Alkalmazott modul: Programozás. Programozási tételek, rendezések Giachetta Roberto

Algoritmusok, adatszerkezetek, objektumok

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

Programozási módszertan. Mohó algoritmusok

OEP Gregorics Tibor: Minta dokumentáció a 3. házi feladathoz 1. Feladat. Elemzés 1

Programozási alapismeretek 1. előadás

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

Rekurzió. Dr. Iványi Péter

A PROGRAMOZÁS ALAPJAI 3. Készítette: Vénné Meskó Katalin

Bevezetés a programozásba I.

Egyszerű programozási tételek

Programozási módszertan

Programozás Minta programterv a 2. házi feladathoz 1.

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

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

Programozás alapjai gyakorlat. 4. gyakorlat Konstansok, tömbök, stringek

Programozás alapjai (ANSI C)

Algoritmusok bonyolultsága

NEM-DETERMINISZTIKUS PROGRAMOK HELYESSÉGE. Szekvenciális programok kategóriái. Hoare-Dijkstra-Gries módszere

2. Visszalépéses stratégia

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

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

Programok értelmezése

A C programozási nyelv II. Utasítások. A függvény.

Függvények növekedési korlátainak jellemzése

Aritmetikai kifejezések lengyelformára hozása

Adatbázis és szoftverfejlesztés elmélet. Programozási tételek

PROGRAMOZÁSI TÉTELEK

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

Gauss-Jordan módszer Legkisebb négyzetek módszere, egyenes LNM, polinom LNM, függvény. Lineáris algebra numerikus módszerei

Hatékonyság 1. előadás

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

Nagyságrendek. Kiegészítő anyag az Algoritmuselmélet tárgyhoz. Friedl Katalin BME SZIT február 1.

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

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

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

Algoritmusok. Dr. Iványi Péter

BASH script programozás II. Vezérlési szerkezetek

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

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

KOVÁCS BÉLA, MATEMATIKA I.

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

2. Visszalépéses keresés

1. Jelölje meg az összes igaz állítást a következők közül!

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

AWK programozás, minták, vezérlési szerkezetek

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

Adattípusok, vezérlési szerkezetek. Informatika Szabó Adrienn szeptember 14.

Webprogramozás szakkör

6. fejezet: Ciklusok

Brósch Zoltán (Debreceni Egyetem Kossuth Lajos Gyakorló Gimnáziuma) Megoldások

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

Eljárások és függvények

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

Kiegészítő előadás. Vizsgabemutató VBA. Dr. Kallós Gábor, Fehérvári Arnold, Pusztai Pál Krankovits Melinda. Széchenyi István Egyetem

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

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

OOP. Alapelvek Elek Tibor

Bevezetés a programozásba. 5. Előadás: Tömbök

Egyenletek, egyenlőtlenségek VII.

Információtartalom vázlata

BASH SCRIPT SHELL JEGYZETEK

1. Alapfogalmak Algoritmus Számítási probléma Specifikáció Algoritmusok futási ideje

11. modul: LINEÁRIS FÜGGVÉNYEK

A C# programozási nyelv alapjai

Leképezések. Leképezések tulajdonságai. Számosságok.

Adatbázis rendszerek Gy: Algoritmusok C-ben

Occam 1. Készítette: Szabó Éva

1. Alapok. #!/bin/bash

Függvények Megoldások

Algoritmizálás, adatmodellezés 1. előadás

Rendezések. A rendezési probléma: Bemenet: Kimenet: n számot tartalmazó (a 1,a 2,,a n ) sorozat

Egyenletek, egyenlőtlenségek X.

Átírás:

Programozási tételek és alkalmazásaik Az ún. programozási tételek bevezetése és alkalmazása hagyományosan az egyik meghatározó pillére az ELTÉ-n folyó programozás oktatásának. A programozási tételek olyan általános célú, absztrakt szinten megfogalmazott egyszerű algoritmus minták, amelyek a tapasztalt fejlesztők szerint is a problémamegoldás és a programkészítés gyakran felhasznált elemi építőkövei. A jellegzetesen ELTE-s szemléletű programozás módszertan egyik korai, ám meghatározó forrása E. W. Dijkstra: A Discipline of Programming című könyve [1], amely 1973-ban jelent meg. A tantárgy bevezetését, kidolgozását és oktatását hosszú éveken végző Fóthi Ákos egyetemi tankönyve [2] teljeskörűen és letisztult formában tartalmazza mindazt, amit közel 30 évig tanultunk (mi, tanítványok és kollégák) az előadásaiból, egy korai, de már hivatalosan kiadott jegyzetéből [3], valamint a tananyag nagyszámú leírt változatából. A tantárgy jelenlegi oktatója Gregorics Tibor is részletesen összefoglalta egy kétkötetes könyvben [4] a tananyag időszerű tartalmát. A programozási tételek aktuális megfogalmazását is ebből a könyvből merítettem. (Hadd maradjak a személyes hangvételű egyes szám első személy mellett, végig.) A programozási tételek olyan általánosan megfogalmazott feladatokra adott (bizonyítottan helyes) absztrakt megoldások, amelyeket egy adott [m, n] egész intervallum és az azon értelmezett f függvény, illetve β tulajdonság fogalomrendszerében írunk fel. Már itt megjegyzem, hogy a feladat gyakran nem így, hanem egy A [1..n] tömbön megfogalmazva jelenik meg. Ilyenkor a tételben szereplő intervallumnak az [1..n] index tartomány felel meg, az f (i) függvényértékek pedig az A[i] tömb elemeiben nyernek elhelyezést. Ez még egy jól belátható absztrakciós lépés az eredeti megfogalmazáshoz képest, így a tömbös változatokat nem foglaljuk külön programozási tételekbe. Ezek az eredeti tételekből kevés módosítással könnyen felírhatók. (A [4] könyv szerzője általánosította a tételeket minden olyan struktúrára, amelyeken egy felsorolás definiálható. Ettől az általánosítástól itt most tekintsünk el.) A programozási tételek formája alig változott napjainkig. A korai verzióhoz képest változások történtek elsősorban a feladatspecifikáció felírásában (nem szerepel a paramétertér), illetve a ciklusszervezés módjában. Az utóbbi lényeges módosítás (korábban az intervallumon kívülről indult a ciklusváltozó, ma pedig az intervallum bal végpontjától). Felvetem majd egy olyan alternatív leírási mód lehetőségét, amelyet a nagy hatású és tekintélyes [5] Algoritmusok (az 1. kiadás fordításának a címe), illetve Új algoritmusok (a 2. kiadás fordításának a címe) könyvben alkalmaznak a szerzők (a szokásos akronímával: CLRS). Ez valamivel közelebb áll a kódolt formához, mint a programozási tételek eredeti változata. Pontosabban, úgy lehetne elhelyezni a szóban forgó CLRS-féle algoritmus leírási módot, mint amelyet az ELTE-s leírás utáni következő lépésben elkészítünk. Ez egy áthidaló állapot a (nálunk szokásos) magasabb absztrakciós szint és a (programozók által is elfogadható) programkód között. Magam is így oldok meg két lépésben iterálva kisebb méretű, oktatási célú feladatokat: (i) az ELTE-s programozási tételek magasabb absztrakciós szintjén; (ii) a CLRS könyv által használt absztrakt függvényekkel tovább lépve a kód felé. 1

Gyakran szembe állítják a struktogramot és a pszeudokódot. Pedig, nincs közöttük összebékíthetetlen ellentét. Noha a különbség több, mint tipográfiai: pl. gyakran máshogyan írunk fel egy IF-et az egyik, illetve a másik rendszerben, mivel a struktogramban nincs egyágú IF-THEN csak két-ágú IF-THEN-ELSE. Meglepő módon, olykor váratlanul kiderül, hogy az üres ELSE-ágakban árválkodó SKIP-ek komolyan támogatják az algoritmus működésének a megértést. Magam mindkettőt használom, de a struktogramot jóval többször, mivel jobbnak, kifejezőbbnek találom. A matematikus hallgatók, akik másodéves korukban találkoznak a struktogrammal, maguktól jutnak hasonló véleményre. Elég megnézni a feltételes maximumkeresés algoritmusának absztrakt leírását a kétféle módszer szerint. Bármilyen akár saját kialakítású leírási forma esetén is megszívlelendő az a figyelmeztetés, hogy tekintsük ezeket a megoldásokat csupán absztrakt algoritmusoknak, amelyek nem tartalmaznak előírásokat a kódolásra. A programkód létrehozása mindig egy önálló kreatív lépés, amely formai szempontból jórészt független az absztrakt megoldástól. A programozási tételeket a kisebb méretű feladatok esetén legtöbbször beszerkesztjük a programkódba (a konkrét feladatnak megfelelő módosítások után). Máskor meg külön eljárást alakítunk egy programozási tételből, amelyet eljáráshívással aktivizálunk. Mindkettőre látunk példát a bemutatott programokban. 1. Melyek a programozási tételek? A programozási tételek köre eredendően hat (6) egyszerű mintát tartalmaz. (Később kialakult a tételeknek egy haladó szintű köre is; ezzel most nem foglalkozunk.) A programozási tételek a legtöbb írásos forrásban (a sorrendtől függetlenül) a következők: 1. Számlálás Számoljuk meg, hogy az [m, n] intervallumban hány helyen teljesül a β feltétel! 2. Összegzés a.) Összegezzük az f függvény értékeit az [m, n] intervallum felett! (Ez így annyira egyszerű feladat, hogy magam nem is tekinteném programozási tételnek, hanem csak az itt következő b) feladatot és megoldását.) b.) Feltételes összegzés: összegezzük az f függvény értékeit az [m, n] intervallum azon pontjai felett, amelyekre teljesül a β tulajdonság! 3. Maximum kiválasztás Határozzuk meg az f függvény legnagyobb értékét a nem-üres [m, n] intervallum felett és adjuk meg azt a helyet is (ha több van, akkor az elsőt), ahol f ezt a legnagyobb értéket felveszi! 4. Feltételes maximum keresés Az előző feladathoz képest annyi az eltérés, hogy a maximum keresése csak azok a helyekre szorítkozik az [m, n] intervallumban, ahol a β tulajdonság fennáll. (Ha egyáltalán nincs ilyen elem, akkor ennek megfelelő választ kell adni.) 5. Szekvenciális (vagy lineáris) kiválasztás Keressük meg az első olyan helyet az m egésztől jobbra indulva, ahol a β tulajdonság fennáll ha tudjuk azt, hogy ilyen hely biztosan létezik! 2

6. Szekvenciális (vagy lineáris) keresés Keressük meg az [m, n] intervallumban az első olyan helyet, ahol a β tulajdonság teljesül, ha nem garantált ilyen hely létezése! (Ha nincs az intervallumban β tulajdonságú hely, akkor ilyen értelmű választ kell adnunk.) A történetileg kialakult elnevezéseket, változatosságukat nem kívánom elemezni, minősíteni, sőt teljeskörűen ismertetni sem. Az elnevezések olykor nem szerencsések, tapasztalható ugyan egy lassú korrekció, de szóhasználat java mára bevésődött. 2. A programozási tételek A programozási tételek forrásnak a [4] könyvet tekintem, amelyet ezennel idézek is. Az analóg módon történő programozás a programkészítés általánosan ismert és alkalmazott technikája. Amikor egy olyan feladatot kell megoldani, amelyhez hasonló feladatot már korábban megoldottunk, akkor az új feladat megoldását a korábbi minta alapján készítjük el. Analóg programozást többféleképpen is lehet végezni. Széles körben használják az analóg algoritmikus gondolkodást, amikor a minta megoldása során alkalmazott gondolatokat és döntéseket lemásolva készítjük el az új feladat megoldását. Kevésbé ismert technika a visszavezetés, amikor nem a mintafeladat megoldási folyamatát, hanem csak annak megoldó algoritmusát másoljuk le. Ehhez szükség van mind az új feladatnak, mind a mintafeladatnak a precíz leírására, a formális specifikációjára, hogy e kettőt összevetve pontosan felfedjük a két feladat közötti hasonlóságokat és eltéréseket. Egy új feladat visszavezetése során a vele hasonló mintafeladat megoldó algoritmusát (a minta algoritmust) sablonként használjuk, kicseréljük benne azokat az elemeket, amelyekben a kitűzött- és a mintafeladat specifikációja is eltér, hogy megkapjuk az új feladatot megoldó algoritmust. A programozási tételek következnek, de nem a fenti, hanem egy általam korábban használt sorrendben. (Nincs most időm átszerkeszteni és végig vezetni a korábbi anyagból kivett sorrendet; esetleg bejöhetne valamilyen hivatkozási ellentmondás is.) Az első két algoritmus érzékeny a ciklusszervezésre, a további négy már kevésbé, vagy egyáltalán nem. A lineáris kereséseknél figyelni arra, hogy miután megtaláltuk a keresett elemet, az azt indexelő ciklusváltozó értékét megnöveljük, így az nem a megtalált elemen áll. Biztosítani kell ezért, pl. egy ind változó bevezetésével, hogy a megtalált elemet ne veszítsük szem elől. (A tételek eredeti, Fóthi-féle formájában ez a jelenség nem lépett fel; erre még visszatérek.) 2.1. Kiválasztás (szekvenciális vagy lineáris kiválasztás) Feladat: Adott egy m egész szám és egy, az m helyen és attól jobbra értelmezett : Z L feltétel. Határozzuk meg az m helytől jobbra eső első olyan számot (ideértve magát az m helyet is), amely kielégíti a feltételt, ha tudjuk, hogy ilyen hely biztosan létezik! Specifikáció: A = (m: Z, ind: Z) Ef = (m=m i m: (i)) Uf = (Ef ind m (ind) i [m..ind 1]: (i) ) 3

Algoritmus: ind := m (ind) ind := ind + 1 Vegyük észre, hogy a programban nincs szükség egy külön i változóra az intervallum bejárásához, ezt a szerepet az ind eredményváltozó tölti be írja a szerző [4]. Saját kiegészítésem: ha a feltételt nem szeretnénk a ciklusfeltételbe beírni (pl. azért, mert több utasítással számítható), akkor egy logikai változó alkalmazásával a következő absztrakt programot kapjuk. Ez már egyaránt használja az i ciklusváltozót és az ind eredményváltozót. l, i := hamis, m l l, ind := (i), i i := i+1 2.2. Keresés (szekvenciális vagy lineáris keresés) Feladat: Adott az egész számok egy [m..n] intervalluma és egy : [m..n] L feltétel. Határozzuk meg az [m..n] intervallumban balról az első olyan számot, amely kielégíti a feltételt! Ha találunk ilyen elemet, akkor azt az l logikai változó igaz értéke jelzi, ind pedig megadja az elem indexét. Ha nincs az [m..n]-ben tulajdonságú elem, akkor ezt az l logikai változó hamis értéke mutatja és ekkor az ind változó értéke irreleváns. Specifikáció: Algoritmus: A = (m: Z, n: Z, l: L, ind: Z) Ef = (m=m n=n ) Uf = (Ef (l = i [m..n]: (i)) (l ind [m..n] (ind) i [m..ind 1]: (i)) ) l, i := hamis, m l i n l, ind := (i), i i := i+1 2.3. Számlálás (adott tulajdonságú elemek megszámolása) Feladat: Adott az egész számok egy [m..n] intervalluma és egy : [m..n] L feltétel. Határozzuk meg, hogy az [m..n] intervallumon a feltétel hányszor veszi fel az igaz értéket! (Ha m > n, akkor egyszer sem.) 4

Specifikáció: A = (m: Z, n: Z, c: N); Ef = (m=m n=n ); Uf = (Ef c = n i= m (i) 1 ) Algoritmus: c, i := 0, m i n (i) c := c+1 SKIP i := i + 1 2.4. Összegzés (feltétel nélküli, illetve adott tulajdonságú elemek összegzése) Feladat: Adott az egész számok egy [m..n] intervalluma és egy f: [m..n] H függvény. (A H halmaz elemein értelmezett összeadásnak és jelölje ezt a + jel.) Határozzuk meg az f függvény [m..n]-en felvett értékeinek az összegét! (Az m > n esetén, vagyis, ha üres az intervallum, akkor ennek az értéke nulla). Ez a feltétel nélküli összegzés. Specifikáció: Algoritmus: A = (m: Z, n: Z, s: H) Ef = ( m=m n=n ) Uf = ( Ef s = f (i) ) n i= m s, i := 0, m i n s : = s + f ( i) i := i + 1 A H halmaz helyén legtöbbször a valós számok R halmazával találkozunk. A bevezetőben mondottak szerint ezt az egyszerű, feltétel nélküli összegzést nem szívesen tartom külön programozási tételnek. A feltételes összegzést viszont igen. Ekkor az intervallum tulajdonságú elemein kell az f függvény értékeit összegezni. Algoritmus: s, i := 0, m i n s := s + f(i) (i) i := i + 1 SKIP 5

2.5. Maximum kiválasztás Feladat: Adott az egész számok egy [m..n] intervalluma és egy f: [m..n] H függvény. A H halmaz elemein értelmezett egy teljes rendezési reláció. Határozzuk meg, hogy az f függvény hol veszi fel az [m..n] nem üres (ez előfeltétel!) intervallumon a legnagyobb értéket, és mondjuk meg, hogy mekkora ez a maximális érték! Specifikáció: Algoritmus: A = (m: Z, n: Z, ind: Z, max: H) Ef = (m=m n=n n m) Uf = (Ef ind [m..n] max = f(ind) i [m..n]: max f(i)) max, ind, i := f(m), m, m+1 i n max < f(i) max, ind := f(i), i SKIP i := i + 1 Találkozhatunk olyan feladatokkal, ahol csak az ind, vagy csak a max értékére van szükség. A második esetben az ind-nek történő értékadás törölhető, de az első esetben a max változóra mindenképpen szükség van. Érdemes megjegyezni, hogy ez az a programozási tétel, amelyet az algoritmusok és adatstruktúrák elnevezésű diszciplína ennek emblematikus műve az [5] könyv felvesz a nyilvántartott és tanulmányozott algoritmusok sorába. 2.6. Feltételes maximumkeresés Feladat: Adott az egész számok egy [m..n] intervalluma, egy f: [m..n] H függvény és egy : [m..n] L feltétel. A H halmaz elemein értelmezett egy teljes rendezési reláció. Határozzuk meg, hogy az [m..n] intervallum feltételt kielégítő elemei közül az f függvény hol veszi fel a legnagyobb értéket, és mondjuk meg, mekkora ez az érték! Lehet, hogy egyáltalán nincs feltételt kielégítő elem az [m..n] intervallumban, vagy m > n. Ekkor az l logikai változó hamis értéke jelezze ezt, és ekkor a max és ind változók értéke irreleváns. A pozitív esetet pedig l változó igaz értéke jelezze! Specifikáció: A = (m: Z, n: Z, l: L, ind: Z, max: H) Ef = (m=m n=n ) Uf = (Ef (l = i [m..n]: (i) ) ( l ind [m..n] max = f(ind) (ind) ( i [m..n]: (i) max f(i)))) 6

Algoritmus: l, i := hamis, m i n (i) l (i) l (i) SKIP max < f(i) l, max, ind := max, ind := f(i), i i := i + 1 SKIP igaz, f(i), i Az elágazás harmadik ága igényelhet egy kevés magyarázatot. Az l logikai változó jelentése az, hogy találtunk-e már tulajdonságú elemet az intervallum bejárása során. Kezdetben még nyilván: nem. Amikor az első ilyen elemre lépünk, akkor kerül a vezérlés a harmadik ágra. Itt l-et át kell állítani igazra, és inicializálni kell a max és az ind változókat, éppen úgy, mint a maximum kiválasztás első lépésében. 3. Az algoritmusok leírási módja Az algoritmusok megadásának módja az ELTE IK-n hagyományosan a struktogram forma. A grafikus kifejező erővel rendelkező leírási módot jobban szeretik a hallgatók, még a matematikusok is előnyben részesítik, noha először pszeudokóddal találkoznak. Magam is ezen a véleményen vagyok. Ugyanakkor legalább is a matematikusoknál nálam, a tantárgyak elvégzése során szabadon lehet pszeudokódot is használni, ha valaki azt kedveli. Akár struktogram, akár pszeudokód a választott eszköz, azon belül egyaránt minimalista jelölésmódot használnak az ELTE-n. Ha ezt a készletet összehasonlítjuk meghatározó jelentőségű [5] könyvben alkalmazott leírási móddal, akkor rögtön szembe tűnik, hogy abban a szerzők bővebb készlettel dolgoznak. - Nálunk, a [4]-ben a struktogram nem függvény, nem alprogram, hanem csak egy absztrakt utasításokból álló vezérlési struktúra, amely megoldja a feladatot. Az [5] szerzői az algoritmusokat (meghívható) absztrakt függvények formájában adják meg, amelyekből a vezérlés az eredményeket visszaadó return utasítás hatására vissza. - A [4]-ben szereplő programozási tételeknél nem találunk fejléc sort ; ilyen csak akkor szerepel az ELTE-s eszköztárban, ha egy absztrakt algoritmus felhasználásra (úgymond meghívásra ) kerül. Az [5] könyvben a függvényeket fejléc sor vezeti be, amely a függvény nevét és input paramétereit tartalmazza. - Míg a [4] mindig saját szervezésű while-ciklust használ, addig az [5]-ben alkalmazzák a for-ciklust is, ha egy keresési tartományon egyszerűen csak végig kell menni. - A [4]-ben leírt ELTE-s felfogás szerint a vezérlés mindig a struktogram alján ér véget. Az [5] könyv megengedi azt, hogy a return utasítás bármely ponton elhagyja a függvény eljárást és output értékkekkel visszatérjen a hívás helyére. 7

- Az előző különbség már eléggé lényeginek mondható. Ennek következménye az alábbi eltérés a ciklusfeltételek kialakításában. A [4]-ben a ciklusfeltételek gyakran összetettebbek, mert logikai kifejezésekkel pontosan meg kell adni a ciklus terminálásának feltételét. Az [5] könyvben szereplő bonyolultabb szervezésű ciklusok feltételei csak azt adják meg, hogy legfeljebb meddig fut az iteráció és a ciklus belsejében elhelyezett return utasítások gondoskodnak az iteráció befejezéséről, igaz, hogy csak abban az esetben, ha ez a függvény eljárást elhagyását (és a vezérlés visszatérését) is jelent egyben. - Az [4]-es ELTE-s feladatmegoldások általában kisebb egységekre tagoltabbak, abból következően, hogy egy-egy alkalmazott programozási tétel megmarad külön egységnek. Az idézett [5] könyvben viszont gyakran beintegrálódik egy alkalmazott programozási tétel a felhasználó eljárásba; szinte nem is tudjuk már azonosítani. (Túl nagy méretű függvény-eljárások ott sem szerepelnek.) Világos, hogy a puritánabb ELTE-s változatra könnyebb kijelenteni, hogy semmilyen implementálási utasítást nem szeretnénk adni, de még sugallani sem, egy feladat absztrakt megoldásában. Az is világos azonban, hogy ha programot kell írni, akkor a mi informatikus hallgatóinknak is el kell jutniuk a programkódhoz, amelyhez a CLRS-féle felfogás közelebb áll meg absztrakt szinten. Ahogyan említettem saját gyakorlatomat, talán célszerű egy ideig két lépésben is megadni az absztrakt megoldást: először a [4]-ben leírt eszköztárral, majd meghozni az [5]-nek megfelelő döntéseket. Véleményem szerint egyébként is eleve, tehát egy megelőző mélyebb, absztraktabb szintű megoldás nélkül is megengedhető az [5]-ben alkalmazott elemek használata. Aki először az [5] stílusú algoritmus-leírással találkozik, az sincs hátrányban velünk szemben. Személyesen azonban örülök, hogy ezzel a szakmai kultúrával találkoztam. Megállapítható, hogy az informatikusok mégis csak érzékenyek arra, hogy a végső absztrakt megoldásuk ne legyen túlságosan távol az implementációtól, a programnyelvek világától. Nézzük sorban az [5]-ben látott vezérlési szerkezeteket: - A for-ciklus használata nem módosítja a megoldás absztrakt szintjét, továbbá kifejezőbb, mint egy while-ciklussal, ha egy tartomány bejárása a feladat. - A fejléc sort úgy lehet tekinteni, mint az eljárás szignatúráját, amely az input és output paramétereket mintegy hangsúlyosan kiemeli a specifikációból. Ha csak az inputot tartalmazza a fejléc, akkor tudatosítjuk, hogy melyek a visszaadott eredmények. - A return utasítás kétségtelenül utal arra, hogy implementáljunk függvényt, de csak utal rá; határozott utasítást biztosan nem ad. - A return utasítás a strukturált programozás követői által is elfogadott módon, legálisan elhagyja azt a vezérlési struktúrát (legtöbbször ciklust), amelyben szerepel. Ezáltal általában mentesíti a programozót az összetett (logikai változóval konjugált) ciklusfeltétel írásától. (Az a realitás, hogy a legtöbb programozó már nem is hajlandó összetett ciklusfeltételt írni, ha megoldható egy alkalmas return -nel a ciklus elhagyása.) 8

(Itt most áttérek pszeudokódra, aminek nincs különösebb jelentősége, csak annyi, hogy ez a leírás így hamarább készül el. A fenti rajzokat az [4] könyv kéziratából vettem át, itt magam nem készítettem ábrát a jegyzetemben igen, de máshogyan, most jelentős időbe telne az új ábrák elkészítése.) Például, a maximum kiválasztás tételét így is meg lehet fogalmazni (a SKIP-ág elhagyásával): MaxKiv (m, n) 1 max, ind := f(m), m 2 for i = m+1 to n 3 if max < f(i) 4 then max, ind := f(i), i 5 return max, ind A szekvenciális keresés (korábban: lineáris keresés 2) programozási tételét is felírjuk fejsorral és return utasítás alkalmazásával. Lehetne for-ciklust alkalmazni és azt elhagyni return-t, de ehhez stílusában jobban illik a while-ciklus. A találat tényét (igaz vagy hamis) nem logikai változó közvetíti, hanem a visszaadott érték: ha m <= i <= n, akkor találtunk béta, azaz (i) tulajdonságú helyet, akkor éppen az i hely az első ilyen; ha viszont az intervallumon kívüli n+1 értéket adjuk vissza, az azt jelenti, hogy az intervallum nem tartalmaz béta ( ) tulajdonságú egész helyet. (Általános szemlélet: a keresés negatív eredményét a keresés helyének egy nem-reális, extremális értéke mutatja.) LinKer2 (m, n) 1 i := m 2 while i <= n 3 if béta (i) 4 then return i 5 else i := i+1 6 return n+1 A szekvenciális keresés leírási módja lényegében olyan, mint amilyen absztrakt kódokat a [5] könyvben láthatunk. Felmerülhet a kérdés, hogy (függetlenül attól, hogy struktogramot vagy pszeudokódot használunk) melyik a jobb: az eredeti puritán változat, vagy ez a bővebb eszköztárú stílus? Melyik formában jegyezzük meg a programozási tételeket? Ezt szívesen az egyénre (hallgatóra, olvasóra) bíznám, azzal a javaslattal, hogy bármit is választ, a leírást tekintse absztrakt algoritmusnak, amely nem tartalmaz kódolási előírást. Magam egy olyan elég konzervatív leírási módot használok, amely közel áll az eredetihez: struktogram, fejléc sorral kiegészítve, for-ciklust is megengedve, de logikai változók használatával a nem-fix lefutású ciklusok feltételében, a return utasítást mellőzve. 9

Ezt követően ahogy fentebb jeleztem még következik az absztrakt függvény [5]-stílusú kialakítása. Ennek megfelelően a programkód (jelenleg a Python nyelven) általában jelentős formai különbségeket mutat az eredeti absztrakt megoldáshoz képest, ugyanis (1) a kódban megjelenik a return utasítás, továbbá (2) a tételben szereplő logikai változók a kódban már gyakran nem szerepelnek, mert (a) a return folytán egyszerűbb lesz a ciklus-szervezés és (b) a negatív választ nem logikai változó, hanem extremális visszaadott érték közvetíti. Ez az algoritmus leírási formát tartom a legkifejezőbbnek absztrakt szinten. Természetesen semmi nehézséget nem jelent a modernebb változat használata sem, különös tekintettel a gyakran forgatott [5] könyv algoritmusaira. 4. A programozási tételek alkalmazása és kódolása Ha egy feladat megoldásában felismerjük egy vagy több programozási tétel alkalmazást, az biztonságot ad az absztrakt megoldás létrehozásában, a programtervezésben és a kódolásban. Ez akkor is igaz, ha végül a programkódban az alkalmazott programozási tétel eredeti alakja megváltozik. Az absztrakt megoldás implementálása, a programkód létrehozása önálló kreatív lépés a számítógépes megoldási folyamatban. Számos példaprogramot mellékelek, így hiteles! Egy programozási tétel formai szempontból alapvetően két módon válhat a programkód alkotó részévé: (1) Gyakoribb az az eset, amikor a szükséges módosításokkal (pl. a béta ( ) tulajdonság konkrét megadásával) a tételt mintegy beszerkesztjük a programkódba. Ekkor a fejsor nyilván nem szerepel a kódban. Ebben az esetben inkább olyan változatot használunk, amelyik nem tartalmaz return utasítást, mivel az egy önálló függvény megírására utal. Előfordul azonban olyan eset (mint például a prím-tulajdonságot eldöntő feladatnál), hogy a tételt befogadó eljárásból éppen a programozási tétel return utasítása jelenti a helyes kilépést. Ilyen esetben a return utasítást tartalmazó változatot be tudjuk integrálni egy eljárás kódjába. (2) Ritkább esetben a programozási tételt önálló függvényként írjuk meg. Ebben az esetben a return utasítást tartalmazó változatot vehetjük alapul. Ekkor a fejsor a függvény definíció első sora lesz. Példát is látunk majd erre a Dijkstra algoritmus kódolása esetén, ahol a feltételes maximumkeresés tételét célszerű külön függvényként átvenni (némi átalakítás mellett). Irodalom [1] E. W. Dijkstra: A Discipline of Programming. Prentice-Hall, Englewood Cliffs, 1973 [2] Fóthi Á.: Bevezetés a programozáshoz. ELTE jegyzet, 1985 [3] Fóthi Á.: Bevezetés a programozáshoz. ELTE Eötvös Kiadó, 2005 [4] Gregorics T.: Programozás, 1. kötet: Tervezés, 2. kötet: Megvalósítás. ELTE Eötvös Kiadó, 2013 [5] Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, Clifford Stein: Új algoritmusok, Scolar Kiadó, 2003 10