ELEMI PROGRAMOZÁSI TÉTELEK 1. FELADATMEGOLDÁS PROGRAMOZÁSI TÉTELEKKEL 1.1 A programozási tétel fogalma A programozási tételek típusalgoritmusok, amelyek alkalmazásával garantáltan helyes megoldást adhatunk a programozási munka során gyakran előforduló, tipikus programozási feladatokra. A programozási tételek nem egyedi feladatokra, hanem feladatosztályokra adnak megoldást, ezért a megfogalmazásuk is általános. Azokat a típusalgoritmusokat tekintjük programozási tételeknek, melyeknek helyessége (matematikai jellegű módszerekkel) bizonyított.. 1.2 A programozási tételek megfogalmazásának elemei - Feladatkitűzés: az általános feladat szöveges formában - Specifikáció: az általános feladatban szereplő adatok (intervallumok, függvények, relációk) megadása, elő- és utófeltételek megadása - Algoritmus: az általános specifikációban szereplő adatok segítségével megfogalmazott megoldás. 1.3 A programozási tételek alkalmazásának lépései - Specifikáljuk a konkrét programozási feladatot. - A specifikáció ismeretében eldöntjük, hogy az adott feladat programozási tétellel megoldható-e. - Ha igen, kiválasztjuk a megfelelő programozási tételt. Néha ez többféleképpen is megtehető. - A tételben szereplő általános elemeket megfeleltetjük az aktuális feladat konkrét adatainak. - A megfeleltetés és a tétel általános algoritmusa alapján behelyettesítés módszerével megadjuk az aktuális feladat megoldását. Megfelelő rutin birtokában a tétel általános algoritmusát és a megfeleltetést nem kell leírnunk, egyből a behelyettesítést végezzük el. 1.4 A programozási tételekkel történő feladatmegoldás hatékonysága Programozási tételek alkalmazásával a megoldásunk biztosan helyes, de nem feltétlenül a leghatékonyabb. A tétel alkalmazása után mindig célszerű hatékonyságelemzést végeznünk. 1
2. A PROGRAMOZÁSI TÉTELEK CSOPORTOSÍTÁSA A programozási tételek a bemenő és kimenő adatok jellege szerint az alábbi módon csoportosíthatók: - Egy sorozathoz egy értéket rendelő tételek. Ide soroljuk azokat is, amelyek egy sorozathoz néhány (kettő, három) egymással összefüggő értéket rendelnek. (Pl. lineáris keresés.) - Egy sorozathoz egy sorozatot rendelő tételek. Pl. Rendezések, kiválogatás. - Egy sorozathoz több sorozatot rendelő tételek. Pl. szétválogatás - Több sorozathoz egy sorozatot rendelő tételek. Pl. Metszet, unió. 3. EGY SOROZATHOZ EGY ÉRTÉKET RENDELŐ, ELEMI PROGRAMOZÁSI TÉTELEK 3.1 Összegzés tétele 3.1.1 Kitűzés Adott egy sorozat, a sorozat elemein értelmezett egy + művelet. Feladat: Határozzuk meg a sorozat elemeinek az összegét! 3.1.2 Specifikáció f:[m..n] -> H / A H-n értelmezett egy + művelet / s: H Előfeltétel: m,n, f adott, m<=n Utófeltétel: s n im f (i) / azaz s tartalmazza az f függvény [m..n] intervallum elemeihez rendelt függvényértékeinek az összegét / Megjegyzések: - A sorozat elemeit a lehető legáltalánosabban egy [m..n] egész intervallumon értelmezett függvényként adhatjuk meg. - A H halmaz a sorozat elemeinek a típusa - A + művelet nem csak összeadás lehet, lehet pl. *, vagy logikai AND, OR stb. Ebben az esetben a 0 kezdőérték a műveletre jellemző semleges érték. (Pl. szorzás esetében 1, AND esetében True) 2
3.1.3 Algoritmus Eljárás Összegez: s:=0 Ciklus I:=m-től n-ig s:=s+f(i) 3.1.4 Példa Feladat: Határozzuk meg két N dimenziós valós elemű vektor skaláris szorzatát! Specifikáció: A,B:Tömb[1..N]:Valós SkalarSzorzat:Valós Ef: A,B adott Uf: SkalarSzor zat N i1 A[i]* B[i] Megfeleltetés: (az összegzés tétel általános elemeivel) m 1 n N f(i) A[i]*B[i] s SkalarSzorzat Algoritmus: Eljárás SkalarSzorzás: SkalarSzorzat:=0; Ciklus I:=1-től N-ig SkalarSzorzat:= SkalarSzorzat + A[i]*B[i] Szürke kiemeléssel láthatóak a behelyettesített kifejezések. Megjegyzés: C alapú programozási nyelvekben a tömbök indexelése 0-val kezdődik. Ennek megfelelően az algoritmusban a ciklus kezdő és végértéke 0-ra és N-1-re módosul. Ez a megjegyzés érvényes a további példákra is. 3.2 Megszámlálás tétele 3.2.1 Kitűzés Adott egy sorozat, a sorozat elemein értelmezett egy T tulajdonság. Feladat: Határozzuk meg a sorozat T tulajdonságú elemeinek a számát! 3
3.2.2 Specifikáció T:[m..n] -> logikai s: egész Előfeltétel: m,n, T adott, m<=n Utófeltétel: s n 1 T i (i) m / azaz s tartalmazza az [m..n] intervallum azon elemeinek a számát, amelyekhez T igazat rendel / 3.2.3 Algoritmus Eljárás Megszamlal: s:=0 Ciklus I:=m-től n-ig Ha T(I) Akkor s:=s+1 Elágazás vége 3.2.4 Példa Feladat: Határozzuk meg egy pozitív egész szám valódi osztóinak a számát! Specifikáció: N:egész ValodiOsztoDb:egész Ef: N adott, N>0 Uf: ValodiOsztoDb N Div 2 1 i2 N mod i 0 Megfeleltetés: (A megszámlálás tétel általános elemeivel) m 2 n N Div 2 /elég a szám feléig vizsgálnunk T(i) N mod i=0 / i osztója N-nek s ValodiOsztoDb 4
Algoritmus: Eljárás ValodiOsztoSzamol: ValodiOsztoDb:=0; Ciklus I:=2-től N Div 2-ig Ha N mod I=0 akkor ValodiOsztoDb:= ValodiOsztoDb + 1 Elágazás vége Szürke kiemeléssel láthatóak a behelyettesített kifejezések. 3.3 Eldöntés tétele 3.3.1 Kitűzés Adott egy sorozat, a sorozat elemein értelmezett egy T tulajdonság. Feladat: Döntsük el, hogy van-e a sorozatban T tulajdonságú elem! 3.3.2 Specifikáció T:[m..n] -> logikai L:Logikai Előfeltétel: m,n, T adott, m<=n Utófeltétel: L i [m..n]: T(i) / azaz L igaz, ha létezik () az [m..n] intervallumban olyan elem, amelyhez T igaz értéket rendel / 3.3.3 Algoritmus Eljárás Eldontes: i:=m Ciklus amíg (i<=n) és nem(t(i)) i:=i+1 L:=(i<=n) 5
3.3.4 Példa Feladat: Adott egy nem üres string. Állapítsuk meg, hogy tartalma palindroma-e, azaz visszafelé olvasva ugyanazt a szöveget kapjuk? (Pl. Géza, kék az ég! ) Megjegyzés: a szöveg előfeldolgozásával (pl. kiválogatás alkalmazásával) elérhető, hogy a stringünk az eredeti tartalomból csak a betűket tartalmazza, szóközök, írásjelek nélkül, nagybetűssé konvertálva. ( GÉZAKÉKAZÉG ) Specifikáció: S:Szöveg Palindroma:logikai Ef: S adott, nem üres, csak az ABC nagybetűit tartalmazza Uf: Palindroma nem( i [1..Hossz(s) Div 2]:S[I] S[Hossz(S) i 1]) / azaz S palindroma, ha az első felében nincs olyan karakter, amely különbözik a stringben hozzá képest szimmetrikusan elhelyezkedő karaktertől / Megfeleltetés: m 1 n Hossz(s) Div 2 T(i) S[I]<>S[Hossz(S)-i+1] L Palindroma Megoldás: Eljárás PalindromaE: i:=1 Ciklus amíg (i<=hossz(s) Div 2) és nem(s[i]<>s[hossz(s)-i+1]) i:=i+1 Palindroma:=(i<= Hossz(S) Div 2) Megjegyzések: - nem(s[i]<>s[hossz(s)-i+1]) helyett hatékonyabb az S[I]=S[Hossz(S)-i+1] feltétel - Hossz(S) Div 2-t célszerű előre kiszámolni, és egy változóban tárolni. 3.4 Kiválasztás tétele 3.4.1 Kitűzés Adott egy sorozat, a sorozat elemein értelmezett egy T tulajdonság, és tudjuk, hogy van a sorozatban T tulajdonságú elem. Feladat: Határozzuk meg az első T tulajdonságú elem sorszámát! 6
3.4.2 Specifikáció T:[m..n] -> logikai Ind:egész Előfeltétel: m,n, T adott, m<=n, i [m..n]: T(i) / azaz, van olyan elem [m..n]-ben, amelyhez T igazat rendel / Utófeltétel: ind [m..n] és T(Ind) és i [m..ind 1]: nem(t(i)) /azaz az Ind az első (legkisebb) olyan elem az [m..n] intervallumban, amelyhez T igaz értéket rendel / 3.4.3 Algoritmus Eljárás Kiválasztás: i:=m Ciklus amíg nem(t(i)) i:=i+1 Ind:=i 3.4.4 Példa Feladat: határozzuk meg az A és B pozitív egészek legkisebb közös többszörösét! Specifikáció: A,B:egész Lkkt:egész Ef: A,B adottak, A>0, B>0 Uf: Lkkt=(A és B legkisebb közös többszöröse, azaz a legkisebb olyan egész szám, amely A-nak és B-nek is többszöröse) Mivel mindig létezik a legkisebb közös többszörös, kiválasztás tételt alkalmazunk. Megfeleltetés: m Max(A,B) / a keresést az A, B pár maximumáról indítjuk n A*B /Legrosszabb esetben A*B lesz a LKKT, egyébként n értékét nem használja az algoritmus T(i) (I mod A=0) és (I mod B=0) /I többszöröse A-nak, B- nek Ind Lkkt 7
Megoldás: Eljárás LKKTKeres: i:=max(a,b) Ciklus amíg nem( (I mod A=0) és (I mod B=0) ) i:=i+1 Lkkt:=i Megjegyzések: ez a megoldás nem túl hatékony az egyesével történő vizsgálat miatt. Gyorsabb, ha Max(A,B)-vel lépkedünk, azaz, egyből a nagyobb szám többszöröseit vizsgáljuk. (pl. 20 és 45 esetén 45, 90, 135 stb.) 3.5 Lineáris keresés tétele 3.5.1 Kitűzés Adott egy sorozat, a sorozat elemein értelmezett egy T tulajdonság. Feladat: Döntsük el, hogy van-e a sorozatban T tulajdonságú elem, és ha van, adjuk meg a sorszámát! 3.5.2 Specifikáció T:[m..n] -> logikai L:Logikai Ind:egész Előfeltétel: m,n, T adott, m<=n Utófeltétel: L i [m..n]: T(i) és L ind [ m.. n] és T ( Ind ) és i [ m.. Ind 1] : nem( T ( i)) / azaz L igaz, ha létezik () az [m..n] intervallumban olyan elem, amelyhez T igaz értéket rendel, és ha létezik ilyen, akkor az Ind az első (legkisebb) olyan elem az [m..n] intervallumban, amelyhez T igaz értéket rendel / 3.5.3 Algoritmus Eljárás LinKer: i:=m Ciklus amíg (i<=n) és nem(t(i)) i:=i+1 L:=(i<=n) Ha L, akkor Ind:=I 8
3.6 Logaritmikus keresés tétele 3.6.1 Kitűzés Adott egy sorozat, a sorozat elemein értelmezett egy < reláció. A sorozat elemei növekvően rendezettek az adott reláció szerint. Feladat: Döntsük el, hogy szerepel-e a sorozatban egy megadott K elem, és ha van, adjuk meg a sorszámát! 3.6.2 Specifikáció f:[m..n] -> H L:Logikai Ind:egész Előfeltétel: m,n,f, < adott, m<=n, f elemei növekvően rendezettek < reláció szerint Utófeltétel: L i [ m.. n] : f ( i) K és L ind [ m.. n] és f ( Ind ) K 3.6.3 A keresés elve A rendezettséget kihasználva keresünk. Először a középső elemmel hasonlítjuk össze a keresett elemet. Ha a keresett elem kisebb, mint a középső elem, akkor a középső elemtől balra lévő elemek között folytatjuk a keresést, ha pedig nagyobb, akkor az attól jobbra lévő elemek között. A keresést ugyanezen az elven folytatjuk, mindaddig meg nem találjuk a keresett elemet, vagy 0 eleműre nem szűkül a keresési intervallum. Utóbbi esetben a keresés eredménytelen. 3.6.4 Algoritmus Eljárás LogKer: E:=m V:=n L:=Hamis Ciklus amíg (E<=V) és Nem(L) I:=(E+V) Div 2 // Kiválasztjuk a középső elemet Elágazás (f(i)<k) esetén E:=I+1 // A jobb felében folytatjuk (f(i)>k) esetén V:=I-1 // A bal felében folytatjuk (f(i)=k) esetén Ind:=I // L:=Igaz Elágazás vége 9
3.6.5 A logaritmikus keresés hatékonysága A logaritmikus keresés sokkal hatékonyabb (gyorsabb), mint a lineáris keresés. Ennek oka a rendezettség kihasználása. N elem esetében a lineáris keresés átlagosan N/2 lépésben végzi el a keresést, a logaritmikus keresés pedig átlagosan log 2 N/2 lépésben. 3.7 Maximum- és minimumkiválasztás tétele 3.7.1 Kitűzés Adott egy sorozat, a sorozat elemein értelmezett egy < reláció. Feladat: Határozzuk meg a sorozat legnagyobb (legkisebb) elemét az adott reláció szerint! 3.7.2 Specifikáció f:[m..n] -> H / H elemein értelmezett egy < reláció Max:H Ind:egész Előfeltétel: m,n, f adott, m<=n, Utófeltétel: ind [m..n] és max f (Ind) és i [m..n]: (max f (i)) /azaz Ind az [m..n] intervallum azon eleme, amelyben f a maximális értékét, max-ot felveszi / 3.7.3 Algoritmus Eljárás MaximumKiválasztás: Ind:=m Ciklus i:=m+1-től n-ig Ha f(i)>f(ind) Akkor Ind:=i Elágazás vége Max:=f(Ind) Megjegyzés: - Fordított reláció esetén az algoritmus a legkisebb elemet határozza meg -> minimumkiválasztás tétele (ez esetben az elnevezéseket is érdemes értelemszerűen megváltoztatni) 10
3.7.4 Feladatok - Adott síkbeli pontok közül válasszuk ki az origótól legtávolabb lévő pontot! - Határozzuk meg az A..B egész intervallum elemei közül azt az egész számot, amelynek a legtöbb prímosztója van! (A>0) 11