680 likes | 886 Views
AAO. Csink László 2008. ősz. Adminisztráció. Előadók: Csink László csink.laszlo@nik.bmf.hu Miklós Árpád miklos.arpad@nik.bmf.hu A tárgy weblapja: http://nik.bmf.hu/csink. A tárgy célja. Ismerkedés az algoritmus fogalmával, egyszerű „klasszikus” algoritmusokkal
E N D
AAO Csink László 2008. ősz
Adminisztráció Előadók: • Csink László csink.laszlo@nik.bmf.huMiklós Árpád miklos.arpad@nik.bmf.hu A tárgy weblapja: http://nik.bmf.hu/csink
A tárgy célja • Ismerkedés az algoritmus fogalmával, egyszerű „klasszikus” algoritmusokkal • Ismerkedés az algoritmusok implementálásához (megvalósításához) szükséges legalapvetőbb adatstruktúrákkal • Bevezetés az objektumorientált programozási paradigma alapjaiba • Algoritmuskészítési készség kialakítása AAO= Algoritmusok, Adatstruktúrák, Objektumok • Mindez az OOP tárggyal való szoros együttműködésben valósul meg
Irodalom Könyvek, amibikből lehet meríteni: • Cormen, Leiserson, Rivest: Algoritmusok (újabb kiadás is, valamint Informatikai algoritmusok) • Trahtenbrot: Algoritmusok és absztrakt automaták • Kotsis et al: Többnyelvű programozástechnika • Lovász L., Gács P.: Algoritmusok Referencia linkek: • Matematikai háttér http://mathworld.wolfram.com/ • Lexikon: http://wikipedia.org/ Ajánlott feladatgyűjtemény (PPKE)(A Kotsis et al könyv mellett): http://digitus.itk.ppke.hu/~lovei/2007-2/feladatok.html
Hogyan készüljenek?Sajnos, igen nagy szokott lenni a bukási arány! • A diák csak vázlatot jelentenek, a vetített anyag nem tankönyv! • Sokakat megtéveszt, hogy az előadásokon nincs névsor ellenőrzés. Ennek ellenére folyamatosan kell tanulni már a félév elejétől, sok gyakorlatra van szükség, a tudásnak „érlelődnie” is kell • Az előadásokon tárgyalt algoritmusokat célszerű C#-ban otthon megírni • A Kotsis könyvben található algoritmusokat elolvasni, megérteni, megpróbálni segítség nélkül megírni • A feladatgyűjtemény feladataira a programokat megírni • Az OOP gyakorlatokon tanultakat hasznosítani
Algoritmus fogalma • Az algoritmus egy eljárás (jóldefiniált utasítások véges halmaza), amelyet valamely feladat megoldására készítünk. A feladat egy adott kezdeti állapotból egy meghatározott végállapotba jut (szakszóval terminál). • Az algoritmus kiszámítási bonyolultsága és hatékony implementációja az alkalmazott adatstruktúrától függ.
Informális és formális definíció • Az algoritmus tipikusan kisebb-nagyobb alkotórészekből épül fel. Az egyszerű algoritmus egy ételrecepthez hasonlítható. • A formális definíció Alan Turing (Turing gép, 1936) és Alonzo Church (lambda kalkulus) matematikusokhoz köthető. (lásd Haladó algoritmusok tárgy a későbbiekben)
Informális megközelítés: ételrecept Informálisan – hétköznapi szavakkal – egy egyszerű algoritmus egy receptnek tekinthető. A recept tartalmazza az adott étel • nevét; • elkészítésének idejét; • a szükséges alkotórészek nevét és mennyiségét; • az elkészítéshez szükséges eszközöket illetve környezetet (például mikrosütő); • az elkészítéshez szükséges eljárásokat meghatározott sorrendben; • az elkészült adagok számát; • a kalóriatartalmat egy adagra vetítve; • az étel eltarthatóságának idejét.
A másodfokú egyenlet „receptje” 1. • Készítsünk algoritmust az ax2+bx+c=0 egyenlet megoldására. • 1. lépés: az input adatok meghatározása Jelen esetben: a, b, cvalós számok • 2. lépés: output adat(ok) meghatározása: egy xvalós szám (egy megoldás, illetve ha a két gyök egybeesik), x1 és x2valós számok (két különböző megoldás), illetve a „nincs valós megoldás”szöveg.
A megoldás menete • Úgy fogjuk a megoldás menetét prezentálni, ahogy tervezés közben „eszünkbe jut” • Óhatatlan, hogy menet közben lesznek még hibák, mert nem pattan ki a tökéletes megoldás az agyunkból egyszerre • Minden lépés után elemezzük, hogy jól működik-e a programunk, és ha nem tökéletes, akkor javítunk rajta
A feladat „receptje”: a hozzávalók • A „recept” adatai: • Név: MASODFOKU • elkészítésének ideje (és szerző): 2006-07-11. CsL • a feltétlenül szükséges adatok neve és típusa: • a,b,c, 3 valós szám (INPUT) • xvalós szám, VAGY x1 és x2valós számok, VAGY”nincs valós megoldás”szöveg (OUTPUT) • az elkészítéshez szükséges eszközök illetve környezet: • Turbo C++ 3.0 (természetesen más is lehetne, például C#) Windows XP operációs rendszer alatt (ez is lehetne más) • az elkészítéshez szükséges eljárások: • gyökvonás, abszolút érték (ezek elkészítettnek tekintett programok) Megjegyzés: Az OOP gyakorlatokon Visual Studio C# környezetben fogunk dolgozni. (A Turbo C++ előnye, hogy ingyenes)
A feladat pontosítása • Hasznos dolog egy konkrét példát megnézni: 4x2-12x+8=0 • A megoldás x1=2; x2=1Erre a feladatra ez a két értékadás tulajdonképpen egy program. Ez a program azonban nem ad megoldást a 3x2+4x-2.11=0 feladatra. Azt szeretnénk, hogy ugyanaz a a program erre a feladatra is megoldást adjon. • Mi a helyzet az 12x+8=0 egyenlettel? Ez már elsőfokú. El kell dönteni, hogy eredetileg a másodfokú, vagy a legfeljebb másodfokú egyenlet megoldását tűztük-e ki célul? • Megállapítjuk, ezen példa kapcsán, hogy a feladat pontos mibenléte gyakran a megoldás során tisztázódik. A feladat specifikációja tehát finomodhat a megoldás közben.
A specifikáció • Oldjuk meg az ax2+bx+c=0 egyenletet minden a, b, c valós szám esetén.Nevezzük a{ax2+bx+c=0 | a, b, c valós számok}problémaosztálynak, melynek a megoldását keressük. • Lehetett volna a problémaosztályt {ax2+bx+c=0 | a, b, c valós számok és a≠0}halmaznak választani, ekkor a megoldási algoritmus kicsit egyszerűbb, de kevésbé általános.
Létezik-e megoldás? • Tudjuk (például mert érettségiztünk ), hogy van megoldóképlet: Ha komplex megoldást nem engedünk meg – azaz a specifikációt úgy finomítjuk tovább, hogy valós x megoldásokat keresünk – akkor nincs megoldás.
Tanulságok • Hajlamosak vagyunk azt gondolni, hogy mindig létezik valamilyen megoldás, talán azért, mert hozzászoktunk a megoldható feladatokhoz a középiskolában. Vannak azonban algoritmussal nem megoldható problémák. Nem oldható meg például a szögharmadolási probléma: tetszőleges szög harmadának megszerkesztése. • Egy probléma algoritmussal való megoldhatóságának kérdése igen mély dolog, lásd incompleteness theorem a wikipedia-ban. (E tételt felállító Kurt Gödelről az az anekdota szól, hogy Einstein csak azért járt be Princetonban az egyetemre, hogy Gödellel sétálhasson haza és beszélgethessenek )
Első nekifutás gy mint egész nem jó, pl. b=1.1., a=1, c=0.2 • VÁLTOZÓK gy, a,b,c VALÓS SZÁM • BEOLVAS(a,b,c) • gy ← (b*b-4*a*c) • HA gy ≥0 AKKOR gy ← GYOKVONAS(b*b-4*a*c) • EGYÉBKÉNT KIIR(nincs valós megoldás) Itt folytatódna a megoldás, de csak akkor, ha a gyökvonás lehetséges volt. Mivel a gy<0 esetben a KIIR végrehajtása után nem akarjuk, hogy a program folytatódjon, ezért trükkösen megcseréljük a feltételt a HA mögött. értékadás
Folytatjuk 6., 7., 8. sorok egybetartozásának jelölése (a zárójelek párban vannak!) • VÁLTOZÓK gy,a,b,c, x1 VALÓS SZÁM • BEOLVAS(a,b,c) • gy ← (b*b-4*a*c) • HA gy <0 AKKOR KIIR(nincs valós megoldás) • EGYÉBKÉNT{ • gy ← GYOKVONAS(b*b-4*a*c) • HA gy=0 AKKOR x1= -b/(2*a) • EGYÉBKÉNT folytatni kell a dolgot • } Piros színnel jelezzük a változásokat az előzőekhez képest.
Tovább folytatjuk (EZ MÉG NEM VÉGLEGES! • VÁLTOZÓK gy,a,b,c, x1,x2 VALÓS SZÁM ag EGÉSZ SZÁM • BEOLVAS(a,b,c) • gy ← (b*b-4*a*c) • HA gy <0 AKKOR ag=1 • EGYÉBKÉNT{ ag=2 • gy ← GYOKVONAS(b*b-4*a*c) • HA gy=0 AKKOR x1= -b/(2*a) • EGYÉBKÉNT{ ag=3 • x1=-b+gy/(2a) • x2=-b-gy/(2a) • } • } • ESETEK ag • 1 : KIIR(nincs valós megoldás) • 2 : KIIR(egy megoldás van: , x1) • 3 : KIIR(két megoldás van:, x1, x2) • ESETEK VEGE
Javítások, megjegyzések Kellenek további zárójelek: • x1=(-b+gy)/(2a) • x2=(-b-gy)/(2a) Feltételezzük, hogy a KIIR argumentumában ha magyar mondat van, akkor a szöveg íródik ki, ha változónév van, akkor a változó értéke. Azt is feltesszük, hogy a BEOLVAS a megfelelő változókba a billentyűzetről megadott adatokat elhelyezi. A BEOLVAS és a KIIR megvalósításával nem „bíbelődünk”. Mi történik, ha a 7., vagy a 9. vagy a 10. sorban a=0 eset áll elő? Ekkor nullával való osztásra utaló hibaüzenet generálódik. Az ilyen esetek kezelésére a legtöbb nyelvben vannak eszközök (ezzel most nem foglalkozunk), hanem megpróbáljuk „előre látni”, hogy ilyen eset előfordulhat.
a=0 eset • HA a=0 AKKOR • Megoldjuk a bx+c=0 egyenletet • EGYÉBKÉNT • Amit eddig csináltunk (a≠0, b,c tetszőleges) Kész programblokk Megírandó programblokk A lépésenkénti finomítás módszerét alkalmazuk, pszeudokód segítségével.
A nyilak jelzik a megfelelő színű zárójelpárokat, azaz hogy melyik AKKOR és EGYÉBKÉNT melyik HA-hoz tartozik. Az alapértelmezés pont olyan, hogy ezek a zárójelek elhagyhatók. • VÁLTOZÓK gy,a,b,c, x1,x2 VALÓS SZÁM • BEOLVAS(a,b,c) • HA a=0 AKKOR • { HA b=0 AKKOR • { • HA c=0 AKKOR KIIR(minden valós szám megoldás) • EGYÉBKÉNT KIIR(nincs megoldás)} • } • EGYÉBKÉNT x1=-c/b • } • EGYÉBKÉNT • Amit eddig csináltunk (a≠0, b,c tetszőleges)
PROGRAM MASODFOKU VÁLTOZÓK gy,a,b,c, x1,x2 VALÓS SZÁM ag EGÉSZ SZÁM BEOLVAS(a,b,c) HA a=0 AKKOR HA b=0 AKKOR HA c=0 AKKOR ag=4 EGYÉBKÉNT ag=5 EGYÉBKÉNT{ ag=6; x1=-c/b} EGYÉBKÉNT{ gy ← (b*b-4*a*c) HA gy <0 AKKOR ag=1 EGYÉBKÉNT{ ag=2 gy ← GYOKVONAS(b*b-4*a*c) HA gy=0 AKKOR x1= -b/(2*a) EGYÉBKÉNT{ ag=3 x1=(-b+gy)/(2a) x2=(-b-gy)/(2a) } } ESETEK ag 1 : KIIR(nincs valós megoldás) 2 : KIIR(egy megoldás van: , x1) 3 : KIIR(két megoldás van:, x1, x2)) 4 : KIIR(minden valós szám megoldás) 5 : KIIR(nincs megoldás) 6 : KIIR(elfajulo egyenlet, egy megoldás:, x1) ESETEK VEGE PROGRAM VÉGE A program (algoritmus) összerakása
Közelítő gyökvonás (Newton módszer) Legyen A>0, emelyből gyököt szeretnénk vonni, és gy1 tetszőleges, például 1. Ekkor elég nagy n-re gyn közel van egy számhoz, amely A négyzetgyöke. Más szóval a gyn sorozat konvergens és határértéke A négyzetgyöke. Ilyenkor elég nagy n-re gyn és gyn+1egy tetszőlegesen előre megadott számnál is közelebb kerülnek egymáshoz. A következőkben gyn helyett gy-t, gyn+1 helyett ujgy-t írunk és iteratíven számolunk.
A gyökvonás programja • // inp adott szám, melyből gyököt akarunk vonni • VÁLTOZÓK in, ujgy, gy, d, eps DUPLAPONTOS • BEOLVAS(inp) • gy = 1.0 • d=1.0 • eps=0.00001 • ISMETELNI HA( d > eps){ • ujgy = (1.0/2)*(gy + inp/gy) • d = | ujgy – gy | • ujgy = gy • } • KIIR(gy) Abszolút érték A piros rész ismétlődik mindaddig, amíg a sárga rész teljesül. Figyeljük meg, hogy dmenetközben változik!
Vigyázat! A fentiek csak azért működtek jól, mert tudtuk (matematikából), hogy gyn konvergens. Ha most akkor ugyan sn+1-sn bármilyen kicsi lehet, sn mégsem konvergens! Tanulság: egy program használhatóságához szükséges, hogy az elméleti megalapozás korrekt legyen! Anélkül, hogy a gynkonvergenciáját bebizonyítjuk, vagy legalább hivatkozunk a megfelelő szakirodalomra, a fenti program nem ad megoldást, mert nem tudhatjuk, hogy véget ér-e a program, és ha igen, korrekt eredményt ad-e?
Példa: Hogyan keresünk algoritmust egy feladatra igazi alkalmazásoknál? • A napi gyakorlatban –ahelyett, hogy magunk készítünk algoritmust – sokszor inkább körülnézünk. Pontosabban: mindig körülnézünk, hogy van-e megoldás a feladatunkra, vagy nekünk kell nekifognunk megcsinálni (kivétel persze a zh vagy vizsga ) • Nézzünk egy példát: tegyük fel, hogy egy szám prím vagy összetett voltát akarjuk megállapítani. • Keresünk egy algoritmus gyűjteményt, például a MathWorld weblapját (ld. referencia linkek): http://mathworld.wolfram.com/ • Mivel jól tudunk angolul , könnyedén elnavigálunk az adott területre: Number Theory, Prime Numbers, Primality Testing.
ERATHOSTENESI SZITA „An algorithm for making tables of primes. Sequentially write down the integers from 2 to the highest number you wish to include in the table. Cross out all numbers which are divisible by 2 (every second number). Find the smallest remaining number . It is 3. So cross out all numbers which are divisible by 3 (every third number). Find the smallest remaining number . It is 5. So cross out all numbers which are divisible by 5 (every fifth number). Continue until you have crossed out all numbers divisible by . The numbers remaining are prime. „ Forrás: MathWorld
Akkor miért nem csináljuk mindig így? • A feladat pontos megértéséhez gyakran el kell kezdeni megoldani a feladatot. Nem mindig van tehát elegendő információnk a feladatmegoldás kezdetén ahhoz, hogy algoritmus adatbázisokat vagy szakirodalmat használjunk. • Ahhoz, hogy a megfelelő megoldási változatot (paraméterek, sebesség, környezet stb.) kiválasszuk, algoritmuselmélet ismeretekre – és implementációs gyakorlatra – van szükségünk, melyet például ez a tárgy is adhat. • Lehet, hogy az adott feladatra nem találunk az igényeinket kielégítő megoldást. • Lehet, hogy a talált megoldásnál jobb jut eszünkbe (hiszen az irodalomban és a weben publikált megoldásokat is kitalálta valaki valamikor).
Egyszerű programozási tételek • Sorozatszámítás • Eldöntés • Kiválasztás • Keresés • Megszámolás • Maximumkeresés
Sorozatszámítás • A múlt évben minden hónapban eltettem a gázszámlát. Szeretném kiszámolni, hogy mennyi pénzbe került az éves gázfogyasztás. A megoldás lépései: • Lenullázok egy gyűjtőváltozót. • A következő két lépést 12-szer ismételem: • Megfogom a soron következő számlát. • Hozzáadom az előző összeghez. • Megvan az összeg.
Pszeudokód VÁLTOZÓK i, sum EGÉSZ, szamla[i] VALÓS(vagy EGÉSZ) i ← 0; sum ← 0; ISMÉTELNI HA( i kisebb mint 12){ sum ← sum + szamla[i]; } KIIR(sum) Január a 0.-dik, február az 1., …, december a 11. hónap a jelölés szerint
Eldöntés Egy tanuló érdemjegyei alapján szeretném eldönteni, hogy kitűnő-e, vagy sem. Kétféle ötlet is lehet: • Ha a jegyei közt van olyan, ami nem ötös, akkor nem kitűnő. • Ha minden jegye ötös, akkor kitűnő. Vizsgáljuk meg először az első ötletet közelebbről! Nézzük végig a jegyeket, először az elsőt, majd sorra a többit, és ellenőrizzűk, hogy ötös-e. Ha találtunk olyat, ami nem ötös, akkor nem kell megnézni a további jegyeket, mert van nem ötös osztályzat, azaz nem kitűnő.
Az 1. számú pszeudokód VÁLTOZÓK tantárgy_szám, i, jegyek[i] EGÉSZ, van_nemotos LOGIKAI i ← 1 ISMÉTELD HA(i ≤ tantárgy_szám) és (jegyek[i] egyenlő 5-tel){ i : ← i+1 } van_nemotos ←(i ≤ tantárgy_szám) HA (van_nemotos) AKKOR KIIR(nem kitűnő) EGYÉBKÉNT KIIR(kitűnő) Végignézem a jegyeket. Az elsővel kezdem. ellenőrizzük a többit is, hogy ötös-e.
Második ötlet Nézzük végig a jegyeket, először az elsőt,majd sorra a többit, és ellenőrizzük, hogy ötös-e. Ha a tömb minden elemét megvizsgáltuk, akkor minden érdemjegy ötös, azaz kitűnő. VÁLTOZÓK tantárgy_szám, i, jegyek[i] EGÉSZ, mind_otos LOGIKAI i ← 1 ISMÉTELD HA(i ≤ tantárgy_szám) és (jegyek[i] egyenlő 5){ i : ← i+1 } mind_otos ←(i > tantárgy_szám) HA(mind_otos) AKKOR KIIR(kitűnő) EGYÉBKÉNT KIIR(nem kitűnő)
Kiválasztás Egy tankör zárthelyi dolgozatai közül válasszuk ki az egyik elégséges dolgozatot. Megoldás: nézzük végig a dolgozatokat, először az elsőt, majd sorra a többit, amíg nem találunk elégséges dolgozatot. Amikor megtaláltunk egy elégségest, akkor ő lesz a kiválasztott.
Pszeudokód VÁLTOZÓK i, sorsz, dolg_szama, dolgozatok[i] EGÉSZ i ← 1 ISMÉTELD HA ( (i ≤ dolg_szama) és (dolgozatok[i] ≠ 2) ) { i ← i + 1 } sorsz ← i // Ha találtunk elégségest, az lesz a megoldás. HA(i <= dolg_szama) AKKOR KIIR(i); EGYÉBKÉNT KIIR ("nincs elégséges") • Hasonlít az eldöntéshez, de más a konklúzió!
Keresés • Ismerjük egy üzlet januári napi bevételeit. Adjunk meg egy olyan napot -ha van-, amikor a bevétel több volt, mint 20,000 Ft. Megoldás: • Nézzük végig a bevételeket, • először az elsőt, • majd sorra a többit, • amíg nem találunk 20,000 Ft-nál nagyobbat. • Ha találtunk ilyet, • akkor van megoldás, és a megoldás a megtalált bevétel sorszáma • különben nincs megoldás
Input adatok generálása Töltsük fel véletlen egészekkel a január tömb elemeit. (Ezt most még nem kell megérteni, a félév végére világos lesz.) int[] januar = new int [32];// 0-tól indul, a 32. lesz jan. 31 ! Random RandomClass = new Random(); for(int i = 1;i <=31; i++) januar[i]=RandomClass.Next(10,30); • 18 26 28 12 …. Január 1, 2, 3, 4, 5, …. Bevételei rendre ezer forintban, akkor január 3.-át kell megtalálnunk. • Persze az is lehet, hogy a bevétel egyetlen napon sem haladja meg a 20 ezer forintot. • A for ciklust fogjuk részletesen taglalni
A kód (a while ciklust fogjuk részletesen taglalni) int i = 1; while (januar[i] < 20) i++;Console.Write(januar[i] + " "); Ez akkor nem jó, ha nincs megoldás, azaz jan. 31.-én (i=32) Is a bevétel kisebb, mint 20. Mitől állna meg a ciklus? Ha a napokszama == 31, akkor: i = 1; while ( (i<=napokszama) && (januar[i] <= 20)) i++; if (i > napokszama) Console.WriteLine("NINCS megoldas"); else Console.Write(i + "dik nap! ");
Megszámolás • Az előző feladatot kicsit módosítjuk. Számoljuk meg, hány napon (ha egyáltalán) volt az üzlet bevétele 20 ezer forintnál nagyobb?
Megszámolás kódja int darab = 0; for (i = 1; i <= napokszama; i++) if (januar[i] > 20) darab++; Console.WriteLine("a nagyobb bevételek száma: "+darab);
Maximum-kiválasztás • Tegnap este a térképet nézegettem. Kiírtam magamnak 20 magas hegy tengerszint feletti magasságát. Adjuk meg az egyik legmagasabb csúcsot! Megoldás: • Megjegyzem az első hegy magasságát. Ezt tekintem a legmagasabbnak. • A többi hegyet sorra végignézem: • Ha valamelyik magasabb, mint az eddigi legmagasabb, akkor az eddigi legmagasabbat elfelejtem, és az újat jegyzem meg. • A végén pont az első legmagasabb hegyet jegyeztük meg.
Maximum-kiválasztás pszeudokódja 1 int hegyekszama = 10; int[] magas = new int [hegyekszama+1]; // mert 1-től indexelünk int i; Random RandomClass = new Random(); for (i = 1; i <= hegyekszama; i++){ magas[i] = RandomClass.Next(10, 26); Console.Write(magas[i]+" "); }
Maximum-kiválasztás pszeudokódja 2 int max = magas[1]; int eddigi = 1; for (i = 1; i <= hegyekszama; i++) if (magas[i] > max) { max = magas[i]; eddigi = i; } Console.WriteLine("az (egyik) legmagasabb sorszáma: "+eddigi+" magassag "+max); // magas[] tartalmát 1-től kezeljük // Ha mondjuk a 2. hegy és a 7. hegy ugyanolyan magas, // és a többi mind kisebb, az eredmény 2 lesz vagy 7? // 2 lesz. Azonban ha > helyett >= kerül be, akkor 7.
Példák • int x = 10; // deklarálás kezdeti értékadássalint y = x;y = 20; // x értéke 10 és y értéke 20 • float v=2.34; double w;
Adatkonverziók A konverzió C# -ban lehet implicit vagy explicit. Ha az átalakítás automatikus, akkor implicit konverzióról beszélünk, ilyenkor nincs adatvesztés. Az explicit konverzió kikényszerített, ilyenkor előfordulhat adatvesztés. Konverzió leggyakrabban függvényhívás paraméter-átadásakor történik (később látunk majd példákat), vagy kevert típusú adatokkal való numerikus számítások esetén.
A nyilak mutatják az implicit konverziós lehetőségeket (referencia táblázat)
Implicit numerikus konverzió long x1; int y1 = 25; x1 = y1; //implicit numerikuskonverzióint ->long Console.WriteLine(x1); int x1; long y1 = 25; x1 = y1;// long -> int nyíl nincs, mi lesz ? // HIBAÜZENET: NEM LÉTEZŐ implicit konverzió! // OK: mert esetleges adatvesztés lehetséges!