Budapesti Mszaki Fiskola Regionális Oktatási és Innovációs Központ Levelez és Távoktatás Bevezetés az algoritmustanba Programozási tételek Segédlet Készítette: Dávid András Villamosmérnök szak 2006. január
Bevezetés Bevezetésképpen szeretnék a kedves Olvasónak, Programozást tanuló kollegának néhány gondolatot, tanácsot leírni. Az els) fontos kérdés, hogy hogyan lehet, szabad, érdemes programozást tanulni. Véleményem szerint programozást tanulni nem lehet (csak) könyvb)l. A legtöbb könyv nekiugrik egy adott programozási nyelv részletes taglalásába, utasításainak ismertetésébe. Nem azt állítom, hogy lehetetlen így megtanulni bizonyos dolgokat, fogásokat, de véleményem szerint így cs)látású lesz az Illet). Ha megtanul C-ben fogásokat, kínkeservvel vált majd Pascalra, vagy bármely más programozási nyelvre. Mivel Önök els)évesek, talán most tanulnak el)ször programozást, szeretném, ha a programozás ízére, felülr)l való szemléletmódra tennének szert. Ehhez szeretnék segítséget adni ezzel a kis jegyzettel. Megjegyzés: A jelen segédlet nem teljes érték:, inkább kiegészít) jelleggel készült. A programozási tételekb)l csak azokat ismertetem részletesen, melyeket a gyakorlaton tárgyalni fogunk, melyekre példákat fogunk megoldani. - 2 -
A Programkészítés menete Egy program készítésekor érdemes betartani az alábbi lépéseket! 1. A feladat megértése. 2. Matematikai modell elkészítése. 3. Algoritmus készítése és leírása valamely algoritmus-leíró nyelven. 4. Algoritmus kódolása valamely programozási nyelven, program elkészítése. 5. Program futtatása, tesztelése, javítása. 6. Dokumentáció készítése (folyamatos feladat). Nézzük egy kicsit részletesebben! 1. A feladat megértése. A feladat kiírója rögzíti, hogy mit szeretne (bizonyos dolgok számára egyértelm:ek, de lehet, hogy nekünk nem). Érdemes letisztázni, kérdezni a feladat kiíróját, hogy jól értelmeztük-e a feladatot. 2. Matematikai modell elkészítése. Készítsük el a feladat megoldásához szükséges matematikai modellt! 3. Algoritmus készítése és leírása valamely algoritmus-leíró nyelven. Készítsük el és rögzítsük a megoldás algoritmusát! Saját szavaikkal el)ször. Egy feladatot meglátva ne kezdjék el lapozgatni a könyveket, egyszer:en csak gondolkozzanak! Mit kell nekem tennem? Már az algoritmust teszteljék papíron! Helyesen m:ködik az algoritmus? Az algoritmus programozási nyelvt)l független! Az algoritmusról és az algoritmus-leíró eszközökr)l kés)bb lesz még szó. 4. Algoritmus kódolása valamely programozási nyelven, program elkészítése. Ha az algoritmus helyesnek t:nik, akkor lássanak neki a kódolásnak, programírásnak! Az els) fontos dolog, hogy válasszuk ki a megfelel) programozási nyelvet! Ha megtaláltuk, akkor kódolhatunk. Nos itt jöhetnek a könyvek! Hogy épül fel az adott nyelv? Hogyan tudom leírni pl. az el)ltesztel) ciklust, stb? Egy adott m:veletet hogyan tudok megvalósítani az adott programozási nyelven? 5. Program futtatása, tesztelése, javítása. Ha elkészült a program, akkor teszteljék különböz) adatokkal. Teszteljék helyes és helytelen adatokkal! 6. Dokumentáció készítése (folyamatos feladat). Készítsenek dokumentációt a programhoz. A dokumentáció része legyen az algoritmus - 3 -
leírása valamilyen algoritmus-leíró nyelven. Miért van erre szükség? Hogy kés)bb is megértsék, hogy mit, miért, és hogyan készítettek az adott programban. Strukturált programozás A programkészítés során törekednünk kell arra, hogy a strukturált programozás alapelveit betartsuk. A strukturált program 3 vezérlési szerkezetet enged meg: Szekvencia: A programutasítások egymás után (a leírás sorrendjében) hajtódnak végre. Elágazás: Egy vagy több feltételt)l függ)en a program végrehajtása két vagy több ágon folytatódhat. Ismétlés, ciklus: Egy vagy több programutasítást ismételten többször kell végrehajtani. Az Algoritmus Hogy épül fel egy program? A program adatokon végzett m:veletek sorozata. A m:veleteket, m:velet sorozatot nevezhetjük algoritmusnak. N. Wirth megfogalmazása szerint: Algoritmusok + Adatok = Program Az algoritmus fogalma Az algoritmus egy probléma, feladat megoldására szolgáló elemi lépések sorozata. Az algoritmus, programozási nyelvt)l független! Az algoritmussal szemben támasztott követelmények: Legyen egyértelm: és jól meghatározott, azaz ugyanazon bemen) adatokra minden esetben ugyanazt az eredményt szolgáltassa! Legyen id)ben és lépésszámban véges, azaz korlátozott hosszú és végrehajtási idej: legyen! Legyen teljes, általános érvény:, azaz különböz) bemen) adatokkal is oldja meg a feladatot, ne egy konkrét problémára, hanem probléma osztályra vonatkozzon! Algoritmus leíró eszközök Algoritmusainkat célszer: rögzíteni valamilyen formában. Az els) mód, hogy az algoritmust írjuk le saját szavainkkal. Fogalmazzuk meg, hogy a leend) programnak mit kell végeznie, és hogyan. Ezek után írjuk le az algoritmust szabványosított formában, algoritmus-leíró eszközökkel, dokumentáljuk az algoritmusunkat. Három fajta eszközzel ismerkedünk meg. - 4 -
1. Folyamatábra. Az egyik legkorábban kialakult megadási mód. Alapjeleit maga Neumann János dolgozta ki. Az egyes szerkezeti elemek között nyilakkal jelöljük a végrehajtási sorrendet. Ennek köszönhet)en igen vadul ugráló programok is születhetnek, minden átgondolt szerkezet nélkül. Az értékadó utasítás illetve valamilyen eljárás téglalapba, az egy vagy többágú kiválasztás rombuszba vagy lapos hatszögbe, az adatáramlás paralelogrammába, a vezérl) utasítások körbe kerülnek. Az ismétlési szerkezeteket elrejtve tartalmazza az ábra. Csak nagy odafigyeléssel és következetességgel érhetjük el a strukturáltságot. El)nye: Rajzjelekkel, folyamatában írja le az algoritmust, könnyen áttekinthet), nyomon követhet). Hátránya: Terjedelmes, nehezen javítható. 2. Stuktogramm. Szintén rajzi jelekkel írja le az algoritmust, de jóval tömörebb formában. A folyamatábrából a nyilakat elhagyjuk. A program egy téglalap, a téglalapot osztjuk tovább. El)nye: Tömör leírást tesz lehet)vé. Hátránya: Nehezen áttekinthet), követhet), javítható. Ma már ritkán használt eszköz. 3. Mondatszer: leírás, pszeudó-kód (majdnem programkód). Az anyanyelvi megfogalmazáshoz hasonló, de annál tömörebb leírási mód. Az él)nyelv pontatlanságait próbáljuk vele kizárni, de még egyszer:en értelmezhet) marad. Már nagyon hasonlít egy programozási nyelven kódolt programhoz. Talán a legelterjedtebb leírási mód. El)nye: Könnyen javítható, áttekinthet). A fontosabb algoritmus-leírási szerkezetek megadása A következ)kben, táblázatos formában áttekintjük a fontosabb szerkezeteket és azok megadási módjait. Szerkezet neve: Adat be és kivitel. Pl. beolvasás, kiírás Magyarázat: Folyamatábra Stuktogramm Pszeudó-kód Változó Be: Kifejezés Ki: Nincs külön rajzi jel Be: Változó Ki: Kifejezés Egy változóba beolvasunk valamilyen eszközr)l (pl. billenty:zetr)l adatot), kiírjuk egy kifejezés értéket. 2 M:veletvégzés, értékadás Magyarázat: Változó:=Kifejezés Változó:=Kifejezés Változó:=Kifejezés Az utasítás hatására a változó felveszi a kifejezés aktuális értékét. Kiértékel)dik a := (értékadó utasítás) jel jobb oldalán álló kifejezés, és értéke betölt)dik a bal oldali változóba. - 5 -
3 Utasítássorozat Utasítás1 Utasítás2 Utasítás1 Utasítás2 Utasítás1 Utasítás2. UtasításN Magyarázat: Az utasításokat a megadott (az ábrán, illetve a leírás) sorrendben kell végrehajtanunk. 4 Feltételes elágazás Feltétel Feltétel Utasítás1 Utasítás2 Ha Feltétel akkor Utasítás1 különben Utasítás2 Utasítás1 Utasítás2 Magyarázat: Ha a feltétel teljesül (igaz), akkor az utasítás1 kerül végrehajtásra, ha nem, akkor az utasítás2. Mindkét esetben folytatódik a program. 5 Növekményes ciklus Cv:=KE, VE, LK Cv:=KE, VE, LK Utasítás Ciklus Cv:=KE-t)l VE-ig, LK-ként Utasítás Utasítás Magyarázat: Növekményes, vagy számlálós ciklus. A Cv (ciklusváltozó) felveszi a KE (kezd)érték) értékét, és amíg a Cv<VE (végérték) addig végrehajtja a ciklusmagban lev) utasításokat. A ciklusmag egyszeri lefutása után a Cv értéke az LK (lépésköz) értékével automatikusan növel)dik. 6 El)l-tesztel)s ciklus Feltétel Feltétel Utasítás Ciklus amíg Feltétel Utasítás Utasítás - 6 -
Magyarázat: A feltétel kiértékelése után (ha igaz), végrehajtódik a ciklusmag (utasítás). A ciklusmag végrehajtása, ismétlése mindaddig folytatódik, amíg a feltétel igaz. Ha a feltétel hamissá válik, az algoritmus a ciklus utáni utasítással folytatódik. El)l-tesztel). Feltételt kiértékeli, majd végrehajtja a ciklusmagot (ha a feltétel igaz). 7 Hátul-tesztel)s ciklus Utasítás Utasítás Feltétel Ciklus Utasítás amíg Feltétel Feltétel Magyarázat: A ciklusmag végrehajtása után a feltétel kiértékel)dik, ha igaz, akkor a ciklusmag még egyszer végrehajtásra kerül. A ciklusmag ismétlése mindaddig folytatódik, amíg a feltétel igaz. Ha a feltétel hamissá válik, az algoritmus a ciklus utáni utasítással folytatódik. A ciklus egyszer mindenképpen lefut. Hátul-tesztel). Végrehajtja a ciklusmagot, majd a feltételt kiértékeli. Ha a feltétel igaz, akkor még egyszer végrehajtja a ciklusmagot. 8, függvény név(paraméterlista) Utasítás Nincs külön rajzi jel név(paraméterlista) Utasítások vége vége 9 Algoritmus, program kezdete, vége Start Nincs külön rajzi jel Program Program vége Stop - 7 -
Programozási tételek Programok készítése során látni fogjuk, hogy bizonyos feladatok, tevékenységek gyakran el)fordulnak. Ezekre a tevékenységekre a programozás fejl)dése során már készítettek általánosított megoldó algoritmusokat, melyeket mi is felhasználhatunk. Ezeket az általánosított algoritmusokat nevezzük programozási tételeknek. A programozási tételek m:ködése és helyessége matematikai úton bizonyított, így ha egy feladatra rá tudunk húzni egy tételt, akkor biztosak lehetünk abban, hogy helyes eredményt fogunk kapni. 13 programozási tételt fogalmaztak meg, ezek közül csak néhánnyal ismerkedünk meg részletesen. A laborgyakorlaton az algoritmusainkat C programozási nyelven fogjuk kódolni, ezért a tételek megfogalmazásánál a sorozatot egydimenziós tömbként (vektor) valósítjuk meg. A vektort 0-tól indexeljük. 1. Sorozatszámítás tétele Néhány példa: Adjuk meg az els) n (pl.) 100 természetes szám összegét! Adjuk meg n faktoriálisát! Ismert a havi fizetésünk 12 hónapra. Adjuk meg éves szinten az átlagfizetésünket! Ismerjük n ember magasságát. Adjuk meg az átlagmagasságot! Általánosítás A felsorolt feladatoknál közös jellemz), hogy az adatok sorozatához egy konkrét értéket rendel. Ezt az értéket egy, az egész sorozaton értelmezett függvény adja. Ezt a függvényt felbonthatjuk értékpárokon kiszámított függvények sorozatára. Minden olyan m:velet szerepelhet e feladattípusban, amelyre a matematika valamilyen egységes jelölést használ. Pl. összeg, szorzat, unió, metszet, logikai m:veletek. Feladat: Adott egy n elem: s számsorozat, és a sorozat elemein értelmezett f függvény. Adjuk meg a sorozat elemeinek f függvény által képzett értékét. Megoldás: Legyen egy változó a, melynek kezd)értéke f 0 ( nullelem ) az adott feladattól függ. Legyen egy f függvény, amely a sorozat elemein értelmezett függvény. (Pl. +, -, *,, ). A megoldás során a sorozat elemin végighaladva vesszük az a változó és a sorozat aktuális elemének f függvényét. - 8 -
Sorozatszámítás(s,n,f,a) a:=f 0 i:=0, n, 1 Sorozatszámítás(s,n,f,a) Változó: i:egész a:elemtípus a:=f 0 Ciklus i:=0-tól n-ig 1-sével a:=f(a,s[i]) vége a:=f(a,s[i]) vége Egy speciális eset: Összegzés tétele Feladat: Adott egy n elem: s számsorozat. Adjuk meg a sorozat elemeinek az összegét! Megoldás: A sorozat elemeinek összegzéséhez a halmozott összegképzést használjuk fel! Legyen egy változónk összeg, mely kezd)értéke 0. Ehhez adjuk hozzá a sorozat 0. elemét, az eredményt helyezzük vissza az összeg változóba! Adjuk hozzá a sorozat 1. elemét, az eredményt helyezzük vissza az összeg változóba! Ezt addig ismételjük, míg a sorozat minden elemét hozzá nem adtuk az összeg változóhoz! Összegzés(s,n,összeg) összeg:=0 i:=0, n, 1 Összegzés(s,n,összeg) Változó: i:egész összeg:elemtípus összeg:=0 Ciklus i:=0-tól n-ig 1-sével összeg:=összeg+s[i] vége összeg:= összeg+s[i] vége Néhány megfontolandó kérdés: Miért van szükség az összeg változó 0 kezd)értékkel való feltöltésére? Hogyan tudjuk az algoritmusunkat szorzatszámító algoritmussá alakítani? - 9 -
2. Eldöntés tétele Néhány példa: Ismerünk n db számot. Van köztük prímszám? Van a tömb elemei között páros szám? Vagy minden elem páros? Egy adott sorozat számtani sorozat? Az osztályunkban van kékszem: lány? Általánosítás Feladat: Adott egy n elem: s sorozat, és a sorozat elemein értelmezett T tulajdonság. a) Döntsük el, hogy van-e T tulajdonságú elem a sorozatban! b) Döntsük el, hogy minden elem T tulajdonságú-e! a) Megoldás: Meg kell vizsgálnunk a sorozat elemeit, hogy T tulajdonságúak-e. Meg kell néznünk az összes elemet? Felesleges, hiszen, ha találunk már 1 db T tulajdonságú elemet, akkor tudunk válaszolni a kérdésre. A válasz egy logikai típusú válasz: igaz vagy hamis. El)l-tesztel) ciklussal dolgozunk, vizsgáljuk az elemeket egymás után. Mikor léphetünk ki a vizsgálatból? Ha találunk T tulajdonságú elemet, illetve, ha már megvizsgáltunk minden elemet, végigértünk a sorozaton és azt tapasztaltuk, hogy egyik elem sem T tulajdonságú (i=n, a sorozatindex egyenl) a sorozat elemeinek számával). Eldöntés(s,n,T,van) i:=0 s[i] nem T tulajdonságú és i<n Eldöntés(s,n,T,van) Változó: i:egész van:logikai i:=0 Ciklus amíg s[i] nem T tul. és i<n van:=(i<n) vége van:=(i<n) vége - 10 -
b) Megoldás: Meg kell vizsgálnunk a sorozat elemeit, hogy mind T tulajdonságúak-e. Meg kell néznünk az összes elemet? Felesleges, hiszen, ha találunk már 1 db nem T tulajdonságú elemet, akkor választ tudunk adni a kérdésre. El)l-tesztel) ciklussal dolgozunk, vizsgáljuk az elemeket egymás után. Mikor léphetünk ki a vizsgálatból? Ha találtunk nem T tulajdonságú elemet, illetve, ha már megvizsgáltunk minden elemet, végigértünk a sorozaton és azt tapasztaltuk, hogy minden elem T tulajdonságú (i=n, a sorozatindex egyenl) a sorozat elemeinek számával). Eldöntés(s,n,T,mind) i:=0 s[i] T tulajdonságú és i<n mind:=(i=n) vége Eldöntés(s,n,T,mind) Változó: i:egész mind:logikai i:=0 Ciklus amíg s[i] T tul. és i<n mind:=(i=n) vége Néhány megfontolandó kérdés: Miért van szükség a ciklus feltételében az i<n (sorozatindex) vizsgálatára? Mi történik akkor, ha az i<n feltételt elhagyjuk? A ciklusból (vizsgálatból való kilépéskor) miért a sorozatindexet ( i ) vizsgáljuk, miért nem az utoljára megvizsgált elemet? 3. Kiválasztás tétele Néhány példa: Adjuk meg a teremben annak a hallgatónak a sorszámát, aki magasabb, mint 120 cm. Vagy fiatalabb 120 évesnél. Biztos, hogy van ilyen. Adjuk meg egy természetes szám legkisebb, 1-nél különböz) osztóját! Biztos, hogy van ilyen, legrosszabb esetben önmaga. Általánosítás Feladat: Adott egy n elem: s sorozat, és a sorozat elemein értelmezett T tulajdonság. Tudjuk, hogy van a sorozatban legalább 1 db T tulajdonságú elem. Adjuk meg az els) T tulajdonságú elem indexét, sorszámát! Megoldás: Hasonlóan az eldöntés tételéhez vizsgálnunk kell egyesével az elemeket. Meddig kell a vizsgálatot végeznünk? Addig, amíg meg nem találjuk az els) T tulajdonságú elemet. Mivel - 11 -
biztosan van a sorozatban 1 db T tulajdonságú elem, így felesleges azt vizsgálnunk, hogy a sorozat végére értünk-e. Kiválasztás (s,n,t,sorsz) i:=0 s[i] nem T tulajdonságú Kiválasztás(s,n,T,sorsz) Változó: i,sorsz:egész i:=0 Ciklus amíg s[i] nem T tul. sorsz:=i vége Néhány megfontolandó kérdés: Miért nem vizsgáljuk azt, hogy a sorozat végére értünk-e? sorsz:=i vége 4. Keresések Néhány példa: Adjuk meg a teremben az els) 160 cm-nél magasabb hallgató sorszámát! Adjuk meg az osztályunkban egy kékszem: lányt! (sorszámát). Nem biztos, hogy van kékszem: lány az osztályunkban. Adjuk meg a sorozatban az els) páros elem sorszámát! Nem biztos, hogy van ilyen. Ismerjük egy üzlet egy havi forgalmát. (Minden napra megadjuk, hogy mennyi volt a bevétel, s mennyi a kiadás). Adjunk meg egy olyan napot, amelyik nem volt nyereséges! Általánosítás Feladat: Adott egy n elem: s sorozat, és a sorozat elemein értelmezett T tulajdonság. Adjuk meg az els) T tulajdonságú elem sorszámát! Nem rendelkezünk azzal az ismerettel, hogy egy adott tulajdonságú elem benne van-e a sorozatban. Ha igen, akkor meg akarjuk tudni a sorszámát is. A keresésre két módszer is használatos. A lineáris keresést akkor alkalmazzuk, ha a sorozat elemei nem rendezettek a tulajdonságnak megfelel)en, míg a bináris vagy logaritmikus keresést akkor, ha a rendezettség fennáll. - 12 -
I) Lineáris keresés tétele Megoldás: A feladat az eldöntés tételének és a kiválasztás tételének az összevonása. Döntsük el, hogy van-e a sorozatban T tulajdonságú elem, és ha van, akkor adjuk meg a sorszámát! A vizsgálóciklusból kilépve a sorozatindex mutatja meg, hogy hányadik elem a T tulajdonságú elem. Keresés (s,n,t,van,sorsz) i:=0 s[i] nem T tulajdonságú és i<n Keresés(s,n,T,van,sorsz) Változó: i,sorsz:egész van:logikai i:=0 Ciklus amíg s[i] nem T tul. és i<n van:=(i<n) Ha van akkor sorsz:=i vége van:=(i<n) van sorsz:=i vége II) Strázsás keresés Feladat: Adott egy n elem: s sorozat. Keressük azt az elemet, amelynek értéke q! Megoldás: A lineáris keresés tételét módosíthatjuk úgy, hogy a keresett elemet q a sorozat végéhez illesztjük, felvesszük n+1. elemként. Ekkor nem kell figyelnünk, hogy a sorozat végére értünk-e. Az n+1. elem, a strázsa )rködik, és biztosítja, hogy ne haladjunk túl a sorozaton. - 13 -
StrázsásKeresés (s,n,q,van,sorsz) i:=0 s[n+1]:=q s[i] nem egyenlõ q StrázsásKeresés(s,n,q,van,sorsz) Változó: i,sorsz:egész q:elemtípus van:logikai i:=0 s[n+1]:=q Ciklus amíg s[i]q van:=(i<n) Ha van akkor sorsz:=i vége van:=(i<n) van sorsz:=i vége III) Bináris vagy logaritmikus keresés Feladat: Adott egy n elem: s rendezett sorozat. Keressük azt az elemet, amelynek értéke q! Megoldás: A megoldó algoritmus során kihasználjuk, hogy a sorozat rendezett. Els) lépésben vizsgáljuk meg a sorozat középs) elemét! Ha ez a keresett elem ( q ), akkor készen vagyunk. Ha a keresett elem ennél kisebb, akkor csak az ezt megel)z)k között lehet, vagyis a keresést a középs) elem el)tti részre alkalmazzuk. Ha a keresett elem nagyobb, akkor természetesen a keresést a középs) elem utáni részre alkalmazzuk. Részintervallumokat fogunk vizsgálni, a részintervallumokat sz:kítjük. - 14 -
BinárisKeresés (s,n,q,van,sorsz) e:=0 u:=n-1 k:=egészrész((e+u)/2) q<s[k] q>s[k] u:=k-1 e:=k+1 BinárisKeresés(s,n,q,van,sorsz) Változó: e,u,k,sorsz:egész q:elemtípus van:logikai e:=0; u:=n-1 [e=sorozat 0.,u=utolsó elem indexe] Ciklus k:=egészrész((e+u)/2) Elágazás q<s[k] esetén u:=k-1 q>s[k] esetén e:=k+1 amíg e<=u és s[k]q van:=(e<=u) Ha van akkor sorsz:=k vége e<=u és s[k] nem egyenlõ q van:=(e<=u) van sorsz:=k vége 5. Megszámolás tétele Néhány példa: Adjuk meg a sorozatban a páros elemek darabszámát! Határozzuk meg, hogy hány család él a létminimum alatt! Határozzuk meg, hogy mennyi kékszem: lány van az osztályunkban! Általánosítás Feladat: Adott egy n elem: s sorozat, és a sorozat elemein értelmezett T tulajdonság. Adjuk meg a T tulajdonságú elemek darabszámát! Megoldás: A megoldás során végig kell haladnunk az egész sorozaton, és megszámolnunk, hogy hány db. T tulajdonságú elemet találunk. Célszer:en egy változót, melynek a kezd)értéke 0 növelünk mindig. - 15 -
Megszámolás (s,n,t,db) db:=0 i:=0, n, 1 Megszámolás(s,n,T,db) Változó: i,db:egész db:=0 Ciklus i:=0-tól n-ig 1-sével Ha s[i] T tul akkor db:=db+1 vége s[i] T tulajdonságú db:=db+1 Néhány megfontolandó kérdés: Miért van szükség a db változó 0 kezd)értékkel való feltöltésére? vége 6. Maximum-kiválasztás tétele Néhány példa: Adjuk meg a sorozatban a legnagyobb elemet! Határozzuk meg a leghidegebb nap sorszámát! Adja meg egy tömb legnagyobb páros elemének az indexét! Általánosítás Feladat: Adott egy n elem: s számsorozat. Adjuk meg a sorozat legnagyobb elemét! Megoldás: Tegyük fel, hogy a sorozat legnagyobb eleme a 0. elem. Ezt tároljuk egy változóban, pl. max. Ezt a változót hasonlítsuk össze a sorozat a többi elemével. Ha találunk a feltételezett legnagyobb elemnél nagyobbat, akkor jegyezzük meg, hogy az új elem a legnagyobb. Mire a sorozat végére érünk, a max változó a sorozat legnagyobb elemét fogja tartalmazni. - 16 -
Maximumkiválasztás (s,n,max) max:=s[0] i:=1, n, 1 Maximumkiválasztás(s,n,max) Változó: i:egész max:elemtípus max:=s[0] Ciklus i:=1-t/l n-ig 1-sével Ha s[i]>max akkor max:=s[i] vége s[i]>max max:=s[i] vége Néhány megfontolandó kérdés: Mi történik akkor, ha a kiindulási feltételkor a max:=0 értéket adjuk meg? Gondoljon arra, ha minden eleme a tömbnek negatív! Hogyan kell módosítani az algoritmust, hogy a legkisebb elemet válassza ki? Mi történik akkor, ha az s[i]>max helyett az s[i]>=max feltétel vizsgálatot írjuk? Gondoljon arra, hogy több azonos elem is lehet a tömbben! Hogyan kell módosítani az algoritmust, ha a legnagyobb elem indexét, sorszámát szeretnénk megkapni? 7. Kiválogatás tétele Néhány példa: Adjuk meg egy sorozat összes páros elemét! Adott egy számsorozat! Válogassuk ki a prímszámokat! Adjuk meg az összes kékszem: lányt az osztályunkban! Általánosítás Feladat: Adott egy n elem: s sorozat, és a sorozat elemein értelmezett T tulajdonság. Válogassuk ki egy külön sorozatba ( d ) az s sorozat T tulajdonságú elemeit! Megoldás: Végig kell vizsgálnunk a sorozat összes elemét. A T tulajdonságú elemeket egy külön sorozatba kiírjuk. - 17 -
Kiválogatás (s,n,d,db,t) db:=0 i:=0, n, 1 Kiválogatás(s,n,d,db,T) Változó: i,db:egész db:=0 Ciklus i:=0-t/l n-ig 1-sével Ha s[i] T tul. akkor db:=db+1; d[db]:=s[i] vége s[i] T tulajdonságú db:=db+1 d[db]:=s[i] Néhány megfontolandó kérdés: Mi történik akkor, ha a db változónak nem adunk kezd)értéket? vége 8. Szétválogatás tétele Néhány példa: Adott egy számsorozat! Válogassuk szét a páros és a páratlan elemeket! Adott egy id)járási el)rejelzés. Adjuk meg külön azoknak a napokat, melyeken fagyot ígérnek, illetve azokat, amikor nem várható fagy! Válogassuk ki két külön sorozatba az osztályunkban a szemüveges és a nem szemüveges tanulókat! Általánosítás Feladat: Adott egy n elem: s sorozat, és a sorozat elemein értelmezett T tulajdonság. Válogassuk ki külön-külön két sorozatba az s sorozat T, illetve nem T tulajdonságú elemeit! Megoldás: Végig kell vizsgálnunk a sorozat összes elemét. A T tulajdonságú elemeket egy dt (elemszáma dbt ), a nem T tulajdonságú elemeket, pedig egy dnt nev: sorozatba (elemszáma dbnt ) helyezzük el. - 18 -
Szétválogatás (s,n,dt,dbt,dnt,dbnt,t) dbt:=0 dbnt:=0 i:=0, n, 1 s[i] T tulajdonságú Szétválogatás(s,n,dt,dbt, dnt,dbnt,t) Változó: i,dbt,dbnt:egész dbt:=0; dbnt:=0 Ciklus i:=0-t/l n-ig 1-sével Ha s[i] T tul. akkor dbt:=dbt+1 dt[dbt]:=s[i] különben dbnt:=dbnt+1 dnt[dbnt]:=s[i] vége dbt:=dbt+1 dt[dbt]:=s[i] dbnt:=dbnt+1 dnt[dbnt]:=s[i] vége 9. Metszet képzés tétele Néhány példa: Adott két számsorozat! Adjuk meg a két számsorozat azon elemeit, melyek mindkét sorozatban megtalálhatók! Adott a 2-vel és 3-mal osztható számok halmaza. Adjuk meg a 2-vel és 3-mal is osztható számok halmazát! (6-tal osztható számok halmaza) Általánosítás Feladat: Adott egy n elem: s és egy m elem: z sorozat. Határozzuk meg a két sorozat metszetét! Megoldás: Halmazokról van szó, feltesszük, hogy minden elem csak egyszer fordul el) a sorozatban. A megoldás során megvizsgáljuk az s sorozat minden elemét, hogy benne van-e a z sorozatban. Ha igen, akkor betesszük egy harmadik (metszet, metszet ) sorozatba. Kiválogatjuk az s sorozat azon elemeit, melyek benne vannak a z sorozatban. - 19 -
Metszetképzés (s,n,z,m,metszet,db) db:=0 i:=0, n, 1 j:=0 j<m és s[i] nem egyenlõ z[j] vége Metszetképzés(s,n,z,m, metszet,db) Változó: i,j,db:egész db:=0 Ciklus i:=0-t/l n-ig 1-sével j:=0 Ciklus amíg j<m és s[i]z[j] j:=j+1 Ha j<m akkor vége db:=db+1 metszet[db]:=s[i] j:=j+1 j<m db:=db+1 metszet[db]:=s[i] 10. Unió képzés tétele Néhány példa: Adott két számsorozat! Adjuk meg a két számsorozat összes elemét! Adott a 2-vel és 3-mal osztható számok halmaza. Adjuk meg a 2-vel vagy 3-mal osztható számok halmazát! Általánosítás Feladat: Adott egy n elem: s és egy m elem: z sorozat. Határozzuk meg a két sorozat unióját! Megoldás: Halmazokról van szó, feltesszük, hogy minden elem csak egyszer fordul el) a sorozatban. A megoldás során az s sorozat minden elemét átmásoljuk az unió sorozatba, majd a z sorozat azon elemeit, melyek nem szerepelnek az s sorozatban szintén beletesszük az unió sorozatba. - 20 -
Unióképzés (s,n,z,m,unio,db) unio:=s db:=n-1 j:=0, m, 1 i:=0 vége Unioképzés(s,n,z,m, unio,db) Változó: i,j,db:egész unio:=s db:=n-1 Ciklus j:=0-t/l m-ig 1-sével i:=0 Ciklus amíg i<n és s[i]z[j] Ha i=n akkor vége db:=db+1 unio[db]:=z[j] i<n és s[i] nem egyenlõ z[j] i=n db:=db+1 unio[db]:=z[j] 11. Összefuttatás tétele Rendezett sorozatok uniója Néhány példa: Egy osztály lány- és fiú névsorának alapján állítsuk össze az osztálynévsort! Általánosítás Feladat: Adott egy n elem: s és egy m elem: z rendezett sorozat. Határozzuk meg a két sorozat unióját! Természetesen a unió sorozat is rendezett lesz. Megoldás: A megoldás során párhuzamosan haladunk a két sorozatban. Az eredménysorozat els) eleme vagy s 0 vagy z 0 lesz. A kisebbet az eredménysorozatba tesszük, és továbblépünk ebben a sorozatban. Újra hasonlítunk két elemet Ha a két elem egyenl), akkor csak az egyiket tesszük az eredménysorozatba, és továbblépünk mindkét sorozatban. Ha az egyik sorozatnak a végére értünk, akkor a másik sorozatot változatlanul az eredménysorozatba másoljuk. - 21 -
Összefuttatás (s,n,z,m,unio,db) 1 i:=0 j:=0 db:=-1 i<n db:=db+1 i<n és j<m 1 unio[db]:=s[i] db:=db+1 s[i]<z[j] unio[db]:=s[i] j<m s[i]=z[j] unio[db]:=s[i] ; j:=j+1 db:=db+1 unio[db]:=z[j] unio[db]:=z[j] j:=j+1 j:=j+1 vége Összefuttatás(s,n,z,m,unio,db) Változó: i,j,db:egész i:=0; j:=0; db:=-1 Ciklus amíg i<n és j<m db:=db+1 Elágazás s[i]<z[j] esetén unio[db]:=s[i]; s[i]=z[j] esetén unio[db]:=s[i]; ; j:=j+1 s[i]>z[j] esetén unio[db]:=z[j]; j:=j+1 Ciklus amíg i<n db:=db+1; unio[db]:=s[i]; Ciklus amíg j<m db:=db+1; unio[db]:=z[j]; j:=j+1 vége - 22 -
12. Rendezések Gyakran a rendezett elemekkel való m:veletvégzés (pl. egy adott tulajdonság keresése) sokkal hatékonyabb, mint rendezetlen elemek esetében. Ezért nagyon fontosak a sorozat elemeit más sorrendbe el)állító algoritmusok. Ezeket az algoritmusokat adott tulajdonság szerinti rendezésnek nevezzük. A kívánt rendezési irány lehet növekv) vagy csökken) Valamennyi ismertetésre kerül) rendezési algoritmusban a növekv) rendezettség elérése a cél. A többféle rendezési módszer közül a legismertebbek algoritmusát adjuk meg. Általánosítás Feladat: Adott egy n elem: s sorozat. Rendezzük az s sorozat elemeit növekv) sorrendbe! I) Rendezés közvetlen kiválasztással. A rendezend) elemek az s sorozat elemei. A els) menetben kiválasztjuk a sorozat legkisebb elemét úgy, hogy a sorozat nulladik elemét, s[0] -át összehasonlítjuk a sorozat soron következ) elemeivel (s[1], s[2],... s[n])-el). Ha az s[0]-ál kisebb elemet találunk, akkor felcseréljük )ket, vagyis ezt a kisebb elemet tesszük s[0] -ba. A menet végére s[0] a sorozat legkisebb elemét tartalmazza. Az s[0] -át leválasztva - mivel már a helyére került - az eljárást s[1] -el folytatjuk, ezt hasonlítjuk össze az (s[2],... s[n]) elemekkel. Az eljárást folytatva - menetenként a soron következ) legkisebb elem kiválasztásával - n-1 menet után a sorozat rendezetté válik. Rendezés(s,n) i:=0, n-1, 1 j:=i+1, n, 1 vége Rendezés(s,n) Változó i,j:egész Ciklus i:=0-t/l n-1-ig, 1-sével Ciklus j:=i+1-t/l n-ig, 1-sével Ha s[i]>s[j] akkor csere(s[i],s[j]) vége s[i]>s[j] Csere(s[i],s[j] - 23 -
II) Rendezés minimum-kiválasztással. A közvetlen kiválasztással történ) rendezés során sokszor feleslegesen végzünk cserét. A felesleges cserék kiküszöbölése érdekében két segédváltozót érték, index vezetünk be. Az érték nev: változó tartalmazza az adott menetben addig megtalált legkisebb elemet, az index pedig annak sorozatbeli sorszámát, indexét. Minden menetben az s sorozat elemeit az érték nev: változóval hasonlítjuk össze, s ha az érték -nél kisebb elemet találunk, akkor azt betesszük az érték nev: változóba, s az index -ben megjegyezzük a szóban forgó elem indexét. A menet végére az érték a sorozat soron következ) legkisebb elemét tartalmazza, az index pedig azt a sorszámot, ahol ezt az elemet találtuk. Cserére csak a menet utolsó lépésében van szükségünk, amikor az érték -ben lev) legkisebb elemet a helyére tesszük. Rendezés(s,n) i:=0, n-1, 1 érték:=s[i] index:=i j:=i+1, n, 1 vége Rendezés(s,n) Változó i,j:egész Ciklus i:=0-tól n-1-ig, 1-sével érték:=s[i] index:=i Ciklus j:=i+1-t/l n-ig, 1-sével Ha érték>s[j] akkor érték:=s[j]; index:=j s[index]:=s[i] s[i]:=érték vége érték>s[j] s[index]:=s[i] s[i]:=érték érték:=s[j] index:=j - 24 -
III) Indexvektoros rendezés Az indexvektoros rendezést akkor használjuk, ha: - szükségünk van az eredeti sorozatra (az eredeti sorrendre). - a sorozatunk egy-egy eleme sok információt tartalmaz (pl. rekord), így a mozgatás id) és munkaigényes. Az indexvektoros rendezés bármely más rendezési algoritmussal egybeépíthet), most a közvetlen kiválasztással történ) rendezés elvével építjük össze. A rendezés során egy segédvektort (indexvektort) alkalmazunk, amelyben a rendezend) sorozat elemeinek a sorszámát, indexét helyezzük el. Az eredeti sorozat elemeit hasonlítjuk egymással, de a szükséges cseréket csak jelezzük oly módon, hogy az indexvektorban a megcserélend) elemek sorszámát, indexét felcseréljük. A rendezés során az elemek sorrendje - az indexvektor tartalma - változik, de a sorozat változatlan marad. Rendezés(s,n) i:=0, n, 1 ind[i]:=i i:=0, n-1, 1 vége Rendezés(s,n) Változó i,j:egész ind:tömb[0..n:egész] Ciklus i:=0-tól n-ig, 1-sével ind[i]:=i Ciklus i:=0-t/l n-1-ig, 1-sével Ciklus j:=i+1-t/l n-ig, 1-sével Ha s[ind[i]]>s[ind[j]] akkor csere(ind[i],ind[j]) vége j:=i+1, n, 1 s[ind[i]]>s[ind[j]] csere(ind[i],ind[j]) - 25 -
IV) Buborékos rendezés A buborékos rendezés alapelve a szomszédos elemek cseréje. Az els) menetben a rendezend) sorozat végér)l elindulva minden elemet összehasonlítunk az el)tte lev)vel. Ha rossz sorrendben vannak, akkor felcseréljük )ket. Az els) menet végére a legkisebb elem a helyére kerül. Minden további menetben ismét a sorozat végér)l indulunk, de egyre kevesebb összehasonlításra van szükségünk, ugyanis a sorozat eleje fokozatosan rendezetté válik. Rendezés(s,n) i:=1, n j:=n, i, -1 vége Rendezés(s,n) Változó i,j:egész Ciklus i:=1-t/l n-ig, 1-sével Ciklus j:=n-t/l i-ig, -1-sével (visszafele) Ha s[j-1]>s[j] akkor csere(s[j-1],s[j]) vége s[j-1]>s[j] csere(s[j-1],s[j]) V) Egyszer) beillesztéses rendezés A kártyás rendezésnél úgy végezzük a rendezést, mintha kártyáznánk, és kezünkbe egyesével vennénk fel az asztalról a kiosztott lapokat. Az éppen felvett lapnak megkeressük a kezünkben lev) már rendezett sorozatban a helyét úgy, hogy közben a nála nagyobbakat egy hellyel elcsúsztatjuk, végül beillesztjük a felvett lapot a neki megfelel) helyre. - 26 -
Rendezés(s,n) i:=1, n M:=s[i] j:=i-1 M<s[j] és j>=0 vége Rendezés(s,n) Változó i,j:egész M:elemtípus Ciklus i:=1-t/l n-ig, 1-sével M:=s[i] j:=i-1 Ciklus amíg M<s[j] és j>=0 S[j+1]:=s[j] j:=j-1 S[j+1]:=M vége s[j+1]:=s[j] j:=j-1 s[j+1]:=m VI) Shell rendezés A Shell módszer nem foglalkozik egyszerre minden rendezend) elemmel, hanem csak az egymástól adott távolságra lev)kkel. A rendezés több menetben történik. Minden menet elején meghatározunk egy lépésközt d, amely azt jelenti, hogy az adott menetben a sorozat egymástól d távolságra lev) elemeit rendezzük. Az utolsó menetben d=1 esetén a sorozat rendezetté válik. A Shell rendezés el)nye, hogy viszonylag kevés m:velettel az eredeti sorozat nagyjából rendezetté válik. Az elemek körülbelül egyszerre haladnak végleges helyük felé. A lépésköz csökkentésével ebben a nagyjából rendezett sorozatban már csak kisebb korrekciókat kell végrahajtanunk Egy adott meneten belül a beszúró rendezést használjuk. - 27 -
Rendezés(s,n) d:=n-1 i:=0 d<1 i<d és i+d<n d:=int(d/2) j:=i+d j<n Rek:=s[j] B:=j-d B>0 és Rek<s[B] s[b+d]:=rek j:=j+d s[b+d]:=s[b] B:=B-d vége Rendezés(s,n) Változó i,j,d,b:egész REK:elemtípus d:=n-1 Ciklus i:=0 Ciklus amíg i<d és i+d<n Ciklus j:=i+d-t/l n-ig, d-esével (lépésköz d) REK:=s[j]; B:=j-d Ciklus amíg B>0 és REK<s[B] S[B+d]:=s[B]; B:=B-d S[B+d]:=REK d:=int(d/2) amíg d<1 vége - 28 -
VII) Gyors rendezés A gyors rendezés során a rendezend) sorozatunkat részekre bontjuk. Kiválasztjuk a sorozat egyik tetszõleges elemét (ezt alapnak vagy strázsának nevezzük), és ehhez az elemhez fogjuk hasonlítani a többi elemet. A sorozatban elõször balról, azaz a sorozat elejérõl indulva lépegetünk egészen addig, amíg a strázsánál kisebb elemet találunk. Ha egy elem nagyobb vegy egyenlõ mint a strázsa, akkor ott megállunk, és a sorozat jobb oldaláról, azaz a végérõl lépegetünk egészen addig, amíg a strázsánál nagyobb elemet találunk. Ha egy elem kisebb vagy egyenlõ mint a strázsa, akkor ott megállunk, és felcseréljük azt a két elemet, ahol megálltunk a lépegetések során. A lépegetést, keresést, cserét a következõ nagyobb illetve kisebb indexü elemnél folytatjuk egészen addig, amíg a két index össze nem ér (találkozik, vagy helyet cserél). Az eljárást, felosztási módszert egészen addig folytatjuk, amíg a felosztandó rész hossza 1 nem lesz. Gyors(tól,ig) Változó bal,jobb,tól,igy:egész bal:=tól jobb:=ig alap:=s[egészrész(tól+ig)/2)] Ciklus Ciklus amíg s[bal]<alap bal:=bal+1 Ciklus 3 amíg s[jobb]>alap jobb:=jobb-1 Ha bal<=jobb akkor csere(s[bal],s[jobb]); bal:=bal+1; jobb:=jobb-1 amíg bal>jobb Ha tól<jobb akkor Gyors(tól,jobb) Ha bal<ig akkor Gyors(bal,ig) vége - 29 -
Gyors(tól,ig) bal:=tól jobb:=ig alap:=s[egészrész(tól+ig)/2] s[bal]<alap bal:=bal+1 s[jobb]>alap jobb:=jobb-1 bal<=jobb CSERE(s[bal],s[jobb]) bal:=bal+1 jobb:=jobb-1 bal>jobb tól<jobb Gyors(tól,jobb) bal<ig Gyors(bal,ig) vége - 30 -