Bevezetés Kedves résztvevő! Először is őszinte örömünket szeretnénk kifejezni, hogy ezt az oktatási formát választotta a tantárgy elsajátításához. A kurzus elvégzése után Ön képes lesz játszva kijönni bármely labirintusból, meg tudja mondani, hogy mikor lesz vége a világnak a tibeti lámák szerint, zárójelek használata nélkül is képes lesz leírni bármilyen matematikai kifejezést, megérti a rekurzió lényegét, tudni fogja az információ tartalmát számolni, algoritmust optimalizálni, számokat, szövegeket ábrázolni, ismerni fogja a számítógép legbelsőbb működését. Bizonyára ismeri a keresés, sorba állítás néhány módszerét, itt újabbakkal és hatékonyabbakkal találkozik. Biztonsággal fog eligazodni a különböző adatszerkezetekben, képes lesz kezelni, és hatékonyan használni őket. A kurzus anyagát három egységben kapja kézhez, s mindegyik elvégzése után lehetősége van személyes konzultációra tanuló társaival, a kurzus vezetőivel, tanáraival. A három egység anyaga a következő: I. A számítógép és az algoritmus A kurzus
193
Embed
Nyíregyházi Főiskola - zeus.nyf.huzeus.nyf.hu/~falu/bevinfo/jegyzet.doc · Web viewKedves résztvevő! Először is őszinte örömünket szeretnénk kifejezni, hogy ezt az oktatási
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Bevezetés
Kedves résztvevő!
Először is őszinte örömünket szeretnénk kifejezni, hogy ezt az
oktatási formát választotta a tantárgy elsajátításához. A kurzus
elvégzése után Ön képes lesz játszva kijönni bármely labirintusból,
meg tudja mondani, hogy mikor lesz vége a világnak a tibeti lámák
szerint, zárójelek használata nélkül is képes lesz leírni bármilyen
matematikai kifejezést, megérti a rekurzió lényegét, tudni fogja az
felesleges DVD-ROM, hangkártya, gyors videokártya, CD-író.
Megfelelő önmérséklettel sokat spórolhatunk. Ha játszani is
szeretnénk a gépen és modern játékokat, akkor spóroljunk,
spóroljunk és spóroljunk. A játékok, mint minden multimédiás
alkalmazás, valósidejű és bonyolult számításokat igényelnek, így
nagyon jó hardver alap kell hozzájuk, ami drága mulatság.
17
Gyakorló feladat: Adjon meg egy napjainkban korszerű
számítógép konfigurációt (pénz nem számít)!
Melyik egységek, jellemzők döntik el egy számítógép
gyorsaságát? Rangsorolja őket!
Állítson össze egy gépet 300.000 Ft-ból!
Gépek árai
Gondolkozzon el, hogy Ön mire használja a számítógépet, s milyenkonfiguráció kellene hozzá!
2. Az algoritmus
2.1 Az algoritmus fogalma
Valószínűleg Ön már hallotta ezt a szót, hogy algoritmus, illetve a
belőle képzett fogalmakat, például algoritmizálható, algoritmizáló
képesség, így nyilván tisztában van magával a szó jelentésével.
Az alábbiakban megismeri az algoritmus számítástechnikai
értelmezését, amely –mint látni fogja– abban tér csak el, hogy
pontosabb és körültekintőbb. Az algoritmus nem más, mint
útmutatás egy probléma megoldáshoz, egyfajta recept, melynek
ismeretében az adott feladatot el tudjuk végezni. Nagyon érdekes
az, hogy mennyire részletes ez az útmutatás, tudjuk-e a megadott
részfeladatok véghezvitelének módját.
Ha egy receptben azt olvassuk, hogy készíts 4 tojásból
piskótatésztát, akkor nyilván ismernünk kell a piskóta készítés
receptjét 4 tojás esetén, tehát az algoritmust hozzá. Fontos az is,
hogy a recept egyértelmű legyen, hiszen a kevés só lehet 1 dkg,
de akár 20 dkg is, ismerni kell a lépések sorrendjét, nem mindegy,
hogy rántotta esetén a tojást tesszük először a serpenyőbe, vagy
az olajat.
Az algoritmus egy meghatározása a következő:
Egy feladat megoldására irányuló, véges számú jól definiált elemi lépések egyértelműen megadott sorozata, melyek véges időn belül véget érnek, s elérik a kitűzött célt.
Nézzünk az algoritmusra egy mindennapi példát, figyeljük meg a
fenti meghatározás elemeit benne. Hogyan tudnánk egy olyan
embernek pontos receptet adni pénzfelvételre egy automatából,
aki még sohasem tett ilyet? Mindenképpen pontosan kell
fogalmaznunk, s biztosítani kell azt, hogy a megadott algoritmus
alapján sikerüljön a művelet.
18
Algoritmus
Lássuk az algoritmust:
1. Helyezd a bankkártyát a befogadó nyílásba
2. Miután az automata behúzta a kártyát, kövesd az automata
kiírásait
Ez így nagyon egyszerű, hiszen segítségünkre volt az a tény, hogy
az automata segíti a pénzfelvételt, algoritmust ad a teendőkre,
tehát egy elemi lépésnek vehettük a kiírásainak követését. Az
általa megfogalmazott algoritmus a következő lépéseket
tartalmazhatja például (a választásainkat vastag betűvel szedtük):
felvétele bizonylat nélkül; pénz felvétele bizonylattal)2. Válassza ki a felvenni kívánt összeget! (1000, 5000, 10 000,
50 000, 100 000, Más összeg)
3. Vegye ki a kártyát!
4. Vegye el a pénzt!
5. Vegye el a bizonylatot!
Ha a kettes pontban nem a pénz felvétele bizonylattal-t választjuk, más lépéseket kínált volna fel az automata. Figyeljük
meg tehát, hogy az egyértelműen megadott sorozat nem azt
jelenti, hogy kötöttek a lehetséges lépések, hanem azt, hogy
világosan meg van adva a lépések sorrendje, azaz nem kell
bizonytalanságban szenvedni az algoritmus alkalmazójának, hogy
melyik lépés legyen a következő. A jól definiált elemi lépés esetünkben azt jelenti, hogy olyan apró lépésekre bontjuk a feladat
elvégzését, melyek értelmezése, elvégzése nem okoz gondot.
Elképzelhető olyan eset is, hogy valaki nem tudja azt, hogy a PIN
kód begépelése után meg kell nyomni a bevitel billentyűt. Ebben
az esetben az algoritmus végrehajtója joggal mondhatja, hogy ez
nem algoritmus, mert nem elemi lépéseket kíván. A példában a
lépések száma véges, viszont nem biztos, hogy véges időn belül véget érnek, hiszen nem biztosítja semmi azt, hogy az ügyfél
hajlandó kötött időn belül elvégezni a beviteleket, a választásokat.
19
Ez ellen természetesen védettek a gyakorlatban ezek a
rendszerek, ha túl sokáig várakozunk, megszakítja a folyamatot az
automata, s ilyenkor nem értük el a kitűzött célt. Egy bankjegy
kiadó automata segítségével fel lehetne felderíteni az automata
által követett algoritmust, de a sokszori próbálkozást elébb-utóbb a
bankkártyánk bánná.
Az algoritmuselméletben nem így határozzák meg az
algoritmust, mint mi a fenti esetben, hanem egy matematikai
objektummal, amit Turing-gépnek neveznek. Segítségével
elkerülhető az olyan problémák felvetése, hogy például mit
tekintsünk elemi lépésnek. Programírás során elemi lépésnek
tekintjük majd azt a tevékenységet, melyre tartalmaz megoldást a
programozási nyelv valamely eszköze, így számunkra megfelelő
az algoritmus fenti alakja.
2.2 Eljárások, melyek nem algoritmusok
Nézzünk néhány érdekes példát, melyek nem lesznek algoritmusok:
A. Harmadoljunk meg egy tetszőleges szöget!
A feladat megoldhatatlansága ismert az Euklédeszi geometriában,
így tudjuk, hogy algoritmust nem tudunk rá adni, viszont figyeljük
meg az elemi lépés fontosságát!
Hatodoljuk meg a szöget, majd ezt kétszerezzük! Nyilván az a
gond, hogy a szög hatodolása nem elemi lépés.
B. Két városból egymással szemben halad egy-egy vonat,
mindkettő 10km/h sebességgel, s közöttük repül oda-vissza
egy fecske 20 km/h sebességgel. Amint eléri az egyik vonatot,
visszafordul, s így tovább. Ha a városok távolsága 30km,
mennyi utat tesz meg a fecske, míg a vonatok találkoznak?
A fecske együtt indul az egyik vonattal, és egy óra múlva
találkozik a másikkal, majd visszafordul 20km megtétele után,
20
Az algoritmus főbb jellemzői
Ön hogyan szokott elmagyarázni valakinek egy algoritmust?Milyen kommunikációs eszközöket használ?
Nem algoritmikus leírások
Szögharmadolás
Végtelen sor
Milyen más geometriailag megoldhatatlan feladatot ismer?
innen 20 perc múlva eléri ismét az egyik vonatot, azaz már 26.66
km tett meg, majd visszafordul. Látható, hogy ezzel a számolási
móddal sohasem érnénk a végére a feladatnak, mert végtelenszer
képes a fecske érinteni a vonatokat. Tehát nem algoritmus, mert
nem véges lépésből áll. A probléma érdekes olyan szempontból,
hogy véges időn belül véget ér, hiszen a két vonat 1.5 óra múlva
találkozik egymással az elindulás után, tehát a fecske által megtett
út kiszámítható, s pontosan 30 km.
Ehhez teljesen hasonló Achilles és a teknősbéka esete:
C. Achilles-t futóversenyre hívja ki a teknősbéka, csak kér 10m
előnyt. Achilles nem fogja utolérni „sohasem” a teknősbékát,
mert mire eléri a teknősbéka indulási pozícióját, addigra onnan
már továbblépett, s mire odaér, ahol volt, ismét távolabb lesz a
béka. Legyen Achilles sebessége 10m/s, a teknősé pedig
1m/s.
Achilles Teknősbéka
10.00m 11.000m
11.00m 11.100m
11.10m 11.110m
11.11m 11.111m
Valóban látható, hogy mindig előtte lesz a teknősbéka, tehát az
eljárás, amely kiírja a fenti táblázatot végtelen lépésben futhat
csak le. Itt is azzal jártunk pórul, hogy az időszeleteket
csökkentjük, hiszen könnyen adódik, hogy 10/9 másodperc múlva
Achilles is 100/9 métert és a teknős is 10+10/9 azaz 100/9 métert
tesz meg.
D. Oldjuk meg az x-a=0 egyenletet úgy, hogy felsoroljuk a
természetes számokat egymásután, s ellenőrizzük
behelyettesítéssel, hogy megfelel-e az adott szám.
Amennyiben a is természetes szám, 0-tól kezdve a felsorolást,
előbb-utóbb elérünk hozzá, s így megvan a megoldás.
Kétségkívül lassabb ez a módszer, mintha megoldanánk az
egyenletet, de mindenképpen algoritmizálható. Ha viszont csak
21
Achilles
Egyenlet
azt kötjük ki a-ról, hogy egész szám, akkor, ha értéke kisebb,
mint nulla, soha sem fogjuk megtalálni a gyököt. Így az első
esetben algoritmusról van szó, a másikban nem.
Nem csak akkor állunk szemben azzal a problémával, hogy nem
tudunk algoritmust adni, ha megoldhatatlan a feladat, hanem
vannak úgynevezett algoritmikusan megoldhatatlan feladatok.
Ezek olyan feladatok, melyeket konkrét esetben meg lehet oldani,
de általánosan nem. Például az úgynevezett dominó feladat:E. Esetünkben a dominók eltérnek a szokásostól, és a következő
alakot veszik fel:
Látható, hogy mindegyik dominón 4 szám van, s az egymás
melletti oldalakon ugyanazon számnak kell lenni a szomszédos
dominókban. Forgatni nem szabad őket, azaz állásuk rögzített, s
ha van egy készletnyi dominónk, az azt jelenti, hogy valahány fajta
dominónk van, de minden fajtából végtelen sok áll
rendelkezésünkre.
A feladat a következő: Le tudjuk-e fedni az egész síkot betartva
játékszabályokat, ha adott egy készlet?
Nyilván meg lehet úgy adni készletet, hogy ez sikerüljön. Elég, ha
a készlet egy darab dominóból áll, melynek ugyanaz a szám van
mind a négy oldalán, de jó lenne a következő két dominó fajtát
tartalmazó készlet is:
22
Dominó feladat
Felvetődik a kérdés, hogy van-e olyan algoritmus, mely bármely
készlet esetén eldönti, hogy befedhető-e a sík a készlet elemeivel.
Sajnos a válasz negatív. Több ilyen nevezetes probléma is van, a
legismertebb az algoritmus elméletben a Turing-gép megállási
problémája, mellyel itt most nem foglalkozunk. Tehát vannak
sajnos olyan problémák, melyeknek megoldása nem
algoritmizálható, s emiatt program sem írható rá. Igazi munkánk
során nem valószínű, hogy sok ilyen problémába ütközünk, így
csak a létezésük ismerete a fontos.
Láthattuk, hogy a következő követelményeink vannak az
algoritmusokkal szemben:
a. Elemi lépésekből álljon
b. Egyértelmű legyen ezek sorrendje
c. Véges számban és
d. Véges időben
e. Megoldják a feladatot
Láttunk néhány olyan „ál” algoritmust, amelyekben a fenti
követelmények közül valamely nem teljesült, így nem tekinthetőek
algoritmusnak.
23
Gyakorló feladat:
Adjon példát olyan „ál” algoritmusra, amely nem felel meg a
„b” követelménynek!
Adjon példát olyan „ál” algoritmusra, amely nem felel meg
az „e” követelménynek!
Az algoritmus jellemzői
2.3 Algoritmus leíró eszközök
Az eddigiek során megfigyelhettük, hogy az algoritmusokat úgy
adjuk meg, hogy felsoroljuk az elemi lépéseket egymásután.
Léteznek más módszerek is az algoritmus megadásra, ezeket
mutatjuk most be. A feladat az, hogy adjuk meg két egynél
nagyobb pozitív egész szám legkisebb nem triviális közös osztóját.
2.3.1 Szöveges körülírás
Az első a már ismert módszer, azaz a körülírás.
1. Jelöljük az első számot A-val, a másodikat B-vel
2. Legyen C értéke kettő
3. Ha C-vel osztható A és B is, akkor vége a számításnak, a
kérdéses szám C
4. Ha C kisebb mind A-nál, mind B-nél növeljük meg C értékét
eggyel, s végezzük el a 3. lépést.
5. Vége a számításnak, nincs a triviálistól különböző osztójuk
2.3.2 Blokkdiagram
A második módszer a blokkdiagrammal való megadás. Egy
blokkdiagram nagyon jól szemlélteti az algoritmus működését,
nyomon követhetőek az elemi lépések egymásutániságai. A
következő elemi lépéseket engedi meg a blokkdiagram:
Az elemi lépés neve Az elemi lépés jele
A blokkdiagram kezdete
A blokkdiagram vége
Adatbekérés
24
START
END
BE:
Algoritmusok megadási–módszerei
Blokkdiagram részei
Adatkiírás
Elágazás
Értékadás
Lépések sorrendje
Megadjuk az iménti feladat blokkdiagramját:
25
KI:
26
2.3.3 Program forráslista
Ugyanez a feladat egy programozási nyelven (Pascal):
program lkko;
var a,b,c:word;
begin
readln(a); Azaz bekérjük A értékét
readln(b); Azaz bekérjük B értékét
c:=2; C-be kettőt rakunk
repeat ismételd a következőeket
if (a mod c =0) ha C osztja A-t
and és
(b mod c=0) C osztja B-t
then akkor
begin
writeln(c); írjuk ki C-t
exit vége
end
else különben
c:=c+1; c legyen eggyel nagyobb
until not ((c<a) and (c<b)); Térj vissza
az ismétlés elejére, ha C kisebb A-nál és B-nél is
writeln('Nincs'); írd ki, hogy nincs
readln
end.
end.
27
Gyakorló feladat: Adja meg egy négyzet oldalaiból a területének,
kerületének kiszámítási algoritmusát szöveges és
blokkdiagramos ábrázolással! Ha ismer valamilyen
programozási nyelvet, akkor írjon programot a problémára!
mindhárom fajta leírással.
Egy-egy feladat megoldására általában több algoritmus is adható.
A cél ilyenkor megállapítani azt, hogy melyik a jobb, vagy pedig
igyekszünk jobb és jobb algoritmusokat keresni.
2.4 Algoritmus bonyolultság
Kérdés az, hogy miként tudjuk mérni az algoritmusok jóságát,
milyen szempontok alapján tudjuk vizsgálni őket. Egy algoritmus
jóságát a bonyolultságával mérjük, azaz minél jobb egy algoritmus,
annál kisebb a bonyolultsága. A következőekben meghatározzuk
ezeket az alapfogalmakat, megismerkedünk néhány
összefüggéssel.
Az algoritmus bonyolultságát az a függvény írja le, amely az algoritmus futásának idő és/vagy helyigényét adja meg a bevitt adatok számában/méretében kifejezve.Láthatjuk, hogy kétfajta bonyolultság van, az egyik az az idő,
amely az algoritmus végrehajtása alatt eltelik, a másik pedig az a
hely, amire szüksége van az algoritmusnak a futása alatt. Az
időbonyolultságot nem a szokásos másodpercben mérjük, hanem
a lépések számával, hiszen így kapunk igazán használható
értéket, ugyanis ezáltal nem függ majd attól egy algoritmus
időigénye, hogy mennyire gyors gépen futtatjuk. A hely
bonyolultságát bájtban is lehet mérni, de említettük, hogy a
bonyolultságot azért mérjük, hogy el tudjuk dönteni, hogy két
algoritmus közül melyik a jobb, így csupán összehasonlítás
céljából mérjük ezeket az adatokat, tehát azt lehet mondani, hogy
az egyiknek több hely kell a másiknál, vagy az egyiknél egyenesen
arányos a hely szükséglet, a másiknál pedig négyzetesen arányos.
Fontos észrevenni azt, hogy a hely és idő szükséglet általában
fordítottan arányos egy-egy feladat esetében, tehát tudjuk úgy
gyorsítani az algoritmusunkat, hogy több helyet adunk neki, vagy
tudjuk csökkenteni a helyfoglalást, de akkor lassabb lesz az
algoritmus. Ezt nevezik a hely és idő kölcsönhatásának, azaz egy
algoritmus esetében a szükséges hely és idő között fordított
arányosság van. Nem azt mondjuk, hogy szorzatuk állandó,
28
Algoritmus bonyolultsága
Idő és helybonyolultsága
csupán azt, hogy ha nő az egyik, csökken a másik. Említettük az
imént, hogy valamilyen függvénnyel szokásos mérni a
bonyolultságot, és arra is rámutattunk, hogy nem kell pontos érték,
csak összehasonlításra szokás meghatározni ezeket a
függvényeket. Ha külön nem mondjuk, akkor mindig az
időbonyolultságról van szó. Szokás beszélni különböző esetekről,
f(n)-nel jelölve a bonyolultsági függvényt:
-A legjobb eset: a számunkra legkedvezőbb esetben adja meg a
feladat lépéseinek számát, azaz f(n) minimuma.
-A legrosszabb eset: a számunkra legkedvezőtlenebb esetben
adja meg a feladat lépéseinek számát, azaz f(n) maximuma.
-Az átlagos eset: a számunkra szokványos esetekben adja meg a
feladat lépéseinek számát, azaz f(n) várható értéke.
Tekintsünk például egy vásárlást. Cipőt szeretnénk venni.
Összesen 100 darab van az üzletben, ebből lehet választani, de
sajnos mindegyik különböző méret, így kénytelenek vagyunk a
cipőket sorra felpróbálni. Az algoritmus bonyolultságát azzal
mérjük, hogy hányat kell felpróbálni, mielőtt kiválasztjuk a leendő
árut. Ekkor a legjobb eset 1, azaz rögtön sikerül az első cipőt
megvásárolni, a legrosszabb az, ha egyik sem fog megfelelni,
tehát száz próbát hajtunk végre, de hiába. Átlagosan vajon
hányszor kell próbálni egy-egy vásárlónak?
Könnyen látható, hogy ha egyforma annak az esélye, hogy egy
cipő megfelel, lesz aki az első, lesz, aki, a második, és így tovább,
lesz, aki a 100. cipővel lesz megelégedve. Ha összeadjuk a
próbálgatások számát minden esetet figyelembe véve, majd
elosztjuk a vevők számával, láthatjuk, hogy átlagosan 50 próbára
lesz szükség.
Nézzük meg ezen a példán a hely és idő kölcsönhatását! Ha
mindegyik cipő mellé odaírjuk a méretet, akkor nyilván nem kell
próbálgatással tölteni az időt, hamarabb megtalálhatjuk a helyes
méretet. Így viszont több helyre van szükségünk, hiszen nem elég
a cipőket tárolni, hanem mellettük még fel kell tüntetni a méretet is.
29
Tudjuk, hogy a gyakorlatban ezt alkalmazzák, így lehetséges
gyorsan vásárolni.
2.4.1 A bonyolultság függvény
A bonyolultságoknál említettük, hogy össze szokták hasonlítani a
függvényeket, sőt általában csak azt vizsgálják, hogy mennyire
növekszik a függvény a bemeneti adatok számától függően, tehát
az úgynevezett növekedési rátát vizsgálják. Ezt általában úgy
végzik el, hogy az adott függvényt összehasonlítják néhány
közismert függvénnyel, például a következőekkel:
Log(n), n, n*log(n), n2, n3, 2n.
A log kettesalapú logaritmust jelöl. Érdemes megfigyelni, hogy
növekedési rátájuk emelkedő sorrendjében soroltuk fel ezeket a
függvényeket, hiszen:
A szám Log(n) N n*log(n) n2 n3 2n
4 2 4 8 16 64 16
8 3 8 24 64 512 256
16 4 16 64 256 4096 65536
Látható, hogy minél nagyobb a szám és minél jobbra helyezkedik
el a táblázatban, annál nagyobb. Van kivétel is, a 4 esetében
láthatjuk, hogy 43>24. Ezért szoktunk beszélni úgynevezett
küszöbszámról, mely túllépése esetén már folyamatosan teljesedik
a növekedési ráta. Algoritmus elméletben egy külön jelölést
használnak az összehasonlításra:
Az „O” (nagy o, ordó) függvény: Ha f(n) és g(n) két pozitív
egész számokra definiált olyan függvény, amelyeknek az a
tulajdonsága, hogy f(n) szinte valamennyi n-re nézve g(n)
valamilyen többszörösével közelíthető, akkor a következőt írhatjuk:
f(n) =O(g(n))
30
A nagy ordó (O)jelölés
Ezzel a jelöléssel tudjuk jelezni, hogy két függvény milyen
viszonyban áll egymással. Ha a fenti egyenlőség igaz, akkor nem
jobb jelentősen egyik a másiknál. Ha viszont azt tudjuk, hogy
1. f(n) =O(n)2. g(n) =O(n2)akkor biztos, hogy érdemesebb azt az algoritmust használni,
melynek bonyolultságát az f függvény méri.
Ha a cipők számát n-nel jelöljük az iménti példában, akkor a
kiválasztás függvénye, azaz az algoritmus bonyolultsága az
átlagos esetben egyenlő n/2-vel.
Az alábbiakban megadjuk néhány algoritmus bonyolultságát:
Szekvenciális keresés: O(n)
Bináris keresés: O(log n)
Buborékrendezés: O(n2)
Összeválogató rendezés: O(n*log n)
Magukkal az algoritmusokkal később fogunk megismerkedni.
2.4.2 Algoritmus optimalizálás
Fontos nagyon felismerni azt, hogy az adott algoritmus hogyan
viselkedik akkor, ha növeljük az adatok számát. A gyakorlatban
általában kétféle algoritmus szokott előfordulni, az egyik futási
ideje a bevitt adatok számának valamilyen polinom függvénye, pl.:
4n3+2n2+5n+6=O(n3),Vagy valamilyen exponenciális függvény, pl.
3n+23n+4n3-6=O(3 n)
Az elsőt polinomiális, a másodikat exponenciális függvénynek
nevezzük. Nyilván jobb a polinomiális, mert gyorsabb algoritmust
ad, az egyik cél a tudományban az, hogy a jelenleg exponenciális
bonyolultságú algoritmusok helyett igyekeznek polinomiális
algoritmusokat keresni.
Tekintsük például a prímszámkereséseket, azaz adjunk meg
algoritmust, mellyel eldönthető egy számról, hogy prímszám-e,
azaz létezik-e egész osztója önmagán és az egyen kívül.
31
Bonyolultsági függvények fajtái
A legegyszerűbb, ha minden tőle kisebb pozitív egész számmal –
kivéve az egyet– elosztjuk, s megnézzük, mennyi a maradék. Ha
csak egyszer is azt találjuk, hogy a maradék nulla, akkor már nem
lesz prímszám. Láthatjuk, hogy ha nem szakítjuk meg az
algoritmust, amikor találunk egy osztót, akkor ez n-2 lépést jelent,
ha n-nel jelöltük a kérdéses számot. Természetesen ha
prímszámról volt szó, nem is tudunk kilépni hamarabb.
Egyszerűsíthetjük a megoldást, ha csak a szám négyzetgyökéig
keressük ezeket a lehetséges osztókat, mivel ha addig nem
találtunk, már biztos nem fogunk, hiszen az osztók párokban
fordulnak elő, ahol a pár két tagjának szorzata egyenlő a számmal.
Amikor sikerül a bonyolultságfüggvényt így csökkenteni,
optimalizálásról beszélünk. Tekintve az idő és hely
bonyolultságot, kétfajta optimalizálást vehetünk figyelembe, az
egyiknél gyorsítani szeretnénk az algoritmust, a másiknál pedig
kevesebb helyen akarjuk megoldani a problémát. Igazi
optimalizálás akkor történik, ha anélkül sikerül jobb algoritmust
találni, hogy változna a másik bonyolultság, vagy szerencsés
esetben az is csökken.
Az alábbiakban mutatunk két algoritmust két szám legnagyobb közös osztójának meghatározására:
Az első leírása:
1. Jelöljük a két számot A-val és B-vel
2. Legyen C=A
3. Ha C osztja A-t és B-t is, akkor a legnagyobb közös osztó C, s
véget ér az algoritmus
4. Ha nem osztja, csökkentsük C értékét eggyel
5. Végezzük el a 3. lépéstől az algoritmust
A második leírása, az úgynevezett euklideszi algoritmus:
1. Jelöljük a két számot A-val és B-vel
2. Ha egyenlők, akkor A (vagy B) a legnagyobb közös osztó, s
véget ér az algoritmus
32
Optimalizálás
LNKO
3. Ha nem egyenlők, akkor a nagyobbikból vonjuk ki a kisebbiket
4. Végezzük el a 2. lépéstől az algoritmust
Egy érdekes algoritmus a következő, mely bemenő adata egy
pozitív egész szám, s kiír egy számot:
1. Jelöljük a bemenő számot N-nel
2. Legyen X=0 és Z=1
3. Növeljük X értékét eggyel
4. Adjuk hozzá Z értékéhez X kétszeresét
5. Növeljük Z értékét eggyel
6. Ha Z nem nagyobb mint N, akkor ismételjük meg az
algoritmust a 3. lépéstől
7. Írjuk ki X értékét
2.3 Néhány nevezetesebb algoritmikusan nem megoldható feladat
A leghíresebb ilyen probléma, hogy írjunk programot, mely eldönti,
hogy egy tetszőleges program beolvasva egy tetszőleges adatsort
megáll-e, vagy végtelen ciklusba kerül. A problémát szokás a
Turing-gépek megállási problémájának is nevezni, s
bebizonyítható, hogy nem oldható meg algoritmikusan.
A következő példánk Hilbert 10. problémája. Hilbert 1900-ban
azon a véleményen volt, hogy minden matematikai probléma
33
Gyakorló feladat: Számolja ki a prímkereső és lnko kereső
algoritmusok bonyolultságát!
Gyakorló feladat: Határozza meg a kimenetet a bemenő adat
függvényeként! Bizonyítsa eredményét! Érdemes néhány számra
kipróbálni az algoritmust, így könnyebben látható, hogy mit csinál.
Kísérletezzen bátran!
A megállási probléma
A Hilbert probléma
megoldható, csak idő kérdése, hogy mikor. Felállított 23 olyan
problémát, melyeket akkor nem tudtak megoldani, és meg volt
győződve arról, hogy a XX. században sem tudják majd. Ebből a
10. probléma a következő volt:
Diofantoszi egyenletnek nevezzük a többváltozós egész
együtthatós algebrai egyenleteket, tehát pl.:
3x3-x2y+6z+5=0
alakú egyenletet, ha bennünket csak az egész megoldások
érdekelnek. Például a fenti egyenlet egy megoldása: x=1; y=2;
z= -1. Hilbert azt a feladatot tűzte ki, hogy találjanak olyan
általános módszert (algoritmust), amely minden egész együtthatós
algebrai egyenlet esetén eldönti, hogy van-e annak egész
megoldása. 1970-ben egy 23 éves matematikus –Matyijaszevics-
bebizonyította, hogy nincs algoritmus ennek eldöntésére.
Természetesen több más matematikus sokéves munkáját is
felhasználta, többek között Davis, Robinson, Myhill, Gödel. Gödel
munkája nyomán vált az ismertté, hogy nem minden matematikai
probléma dönthető el algoritmikusan.
Összefoglalás
Ön ezt a fejezetet elsajátítva tisztában van az alapvető számítógép
konfigurációkkal, tanácsot tud adni számítógép vásárlás vagy
fejlesztés esetén, bár igazán akkor lehet szakember ilyen téren az
ember, ha naponta olvassa a szakmai újságokat.
Tudja az algoritmus fogalmát, tud bonyolultságot számolni, s így
összehasonlítani algoritmusokat. Ismeri az algoritmikusan
megoldhatatlanság fogalmát, s ezekre tud példát is mondani.
34
Ajánlott szakirodalom
http://hardver.lap.hu
Dr. Cserny László: Mikroszámítógépek, Vác, Váci ÁFÉSZ nyomda,
Kutat ásnak ketten, egyik már lent van a félig kész üregben, a
másik pedig fent a gödör szélén. Mivel lent sötét van, s nem lehet
lelátni, a felső munkás lekiált:
–Mennyi?
–Öt! –hangzik a válasz, melytől nem lett okosabb a kérdező, ezért
pontosítást várón kérdezi:
–Mi öt?
A lent dolgozó munkás is szeretne pontosabb információhoz jutni,
ezért visszakérdez:
–Mi mennyi?
Ebben a dialógusban rögtön fontos dolgok kerülnek napvilágra,
például az adat és az információ fogalma közötti különbségek.
Az Idegen szavak és kifejezések kéziszótára szerint:
Információ:lat
1. Felvilágosítás, tájékoztatás
2. hírközlés
3. értesülés, adat
4. híranyag, a közlés tárgya
5. inf elektronikus úton továbbított jel; hír
Láthatjuk, hogy az információ definiálásában szerepet játszik az
adat fogalma, s valóban általában együtt emlegetik ezt a két
fogalmat. Legegyszerűbben úgy jellemezhetjük kettőjük viszonyát,
hogy az információ nem más, mint értelemmel bíró adat. De akkor
mi az adat? Erre is adhatunk egyszerű körülírást: Az adat az
információ rögzített formája. Mint láthatjuk, az adat nincs meg az
információ nélkül, s az információ is kívánja az adat jelenlétét.
40
Próbáljuk meg feloldani ezt az ellentmondást a következőekben,
megismerve néhány használatos definícióját az adatnak és az
információnak, s végül az általunk a továbbiakban használt
fogalmát.
Az adat egyik értelmezése a következő:
Fogalmak, tények, jelenségek, események olyan formalizált
ábrázolása, amely emberi vagy gépi értelmezésre, feldolgozásra,
közlésre alkalmas.
Egy másik frappáns, de csak számítástechnikai megközelítés:
Az adat az a legkisebb egység, amivel műveletet tudunk végezni.
Tehát pl az a szó, hogy „alma” adat abban az esetben, ha nem
tudom tovább bontani, de abban az esetben nem, ha
meghatározhatom az első betűjét, ugyanis akkor már az „a” mint
egy betű lesz az adat.
A mi értelmezésünk a következő lesz:
Az adat jelentésétől megfosztott jelsorozat.Ebben a fejezetben s végig a hátralévő tananyagban azzal fogunk
foglalkozni, hogyan ábrázoljuk ezeket a jelsorozatokat, illetve most
már használhatjuk azt a kifejezést is, hogy adatokat. Látni fogjuk,
hogy egy-egy jelsorozat értelmezése más és más lesz, aszerint,
hogy mit jelent, tehát milyen információ tartalma volt eredetileg.
Lássunk néhány információ definíciót is, mielőtt a miáltalunk
használtat megadjuk:
Az információ a valóság reprezentációján végzett transzformáció,
mely végső soron a nyelő (ember esetében az agy) terméke.
Kicsit nyakatekert a definíció, de mindenképpen hasznos megállni
itt egy pillanatra. Azt látjuk, hogy az információ a valóságból
táplálkozik, de a megjelenéséhez még hozzáadódik egy
transzformáció, ami nem más, mint az értelmezés, ez pedig
személyenként más és más lehet.
Más tartalommal bír egy időjárás jelentés annak, aki kirándulni
megy, s annak is, aki esernyőt árul.
Általában az információ kinyerésére nem elegendő maga a
reprezentáció, szükség van még úgynevezett háttér információkra,
41
Az adat
Az információhoz szükséges információk
amik lehetnek az egyén személyes tapasztalatai, vagy az adott
társadalmi-szociológiai rendszer velejárói.
Ha valaki Magyarországról Londonba érkezik, bizony kell egy kis
idő, míg megszokja, hogy a busz nem balról, hanem jobbról jön,
így az az információ, hogy közeledik a busz, mást jelent itthon, s
mást Angliában.
Az információ egy másik kellemes definíciója:
Értelemmel bíró adat.
Rövid és frappáns, de kihagyja az információt felfogót, mint olyat,
aki maga is alakíthatja az információt. Mi ezentúl a következő
definíciót használjuk:
Információnak tekintünk mindent, ami bizonytalanságot szüntet meg.Egy fontos észrevételt is tehetünk, az adat és az információ
egységét szemlélve:
Az információ a tartalmi, az adat a formai oldalát jelenti ugyanannak a közleménynek, vagy jelsorozatnak.Mint láthatjuk, mi mindenesetben az adaton írott adatot értünk, ami
számítástechnikában nagyon is helyénvaló.
1.1 Az információ mérése
Az információ tehát attól nagyobb, ha nagyobb bizonytalanságot
szüntet meg. Jó lenne valahogy mérni, azaz egy konkrét számot
hozzárendelni a különböző információtartalmakhoz. Milyen
elvárásaink legyenek?
a) Ha nem történik bizonytalanság csökkentése, akkor legyen
I(X)=0, ahol I(X) az X esemény információ tartalma.
b) Ha felére csökken a bizonytalanság, akkor legyen I(x)=1, így
ha igen-nem válaszokra képes valaki, akkor pontosan
megkaphatjuk a szükséges kérdések számát, ha ügyesen
kérdezünk, tehát minden kérdésünkkel felezzük a bizonytalan
elemek számát a halmazban. Az ügyes kérdezés azt is
42
Információ
Információ és adat összefüggése
Az információ–tartalmat mérő függvény tulajdonságai
biztosítja, hogy a válasz igen/nem volta nem fogja befolyásolni
a kapott információt.
Például ha kártyalapra kérdezünk, akkor első lépésben a
következőt érdemes kérdezni: Szám van rajta (vagy figura)?
c) Kötődjön a függvény az esemény valószínűségéhez, hiszen
minél kisebb a valószínűség, annál nagyobb bizonytalanságot
szüntet meg, azaz valamilyen egyenes arány „féleség” legyen
a valószínűség reciproka és az információ tartalom között
olyan értelemben, hogy nagyobb reciprokhoz nagyobb
információ tartalom kötődjön.
Ezeket figyelembe véve alkották meg a következő képletet, azaz
függvényt:
I(X)=log(1/p(X))vagy másképpen I(x)= - log(p(x)). A két képlet ugyanaz, csak a
másodikban kihasználtuk, hogy egy szám reciproka egyenlő a –1.
hatványával, s a logaritmus azonosságai miatt ez az előjel kivihető
a logaritmus elé.
Vizsgáljuk meg ezt a képletet. Ha egy x esemény valószínűsége
100%, akkor p(x)=1. Egy reciproka egy, így I(x)=log 1. Mivel 20=1,
így I(x)=log 20=0. Tehát látjuk, hogy a biztos esemény nem ad
információt, vagy más szóval információ tartalma nulla.
Valóban, ha annyit tudunk egy balesetet okozó
személygépkocsiról, hogy fekete volt a gumi a kerekén, nem
jutottunk információhoz (tekintsünk el az extrém esetektől).
Ha egy esemény valószínűsége pici, reciproka nagy lesz, és így a
logaritmusa is. Nézzünk egy érdekes példát!
Mivel egy céltáblán végtelen sok pont van, annak a valószínűsége,
hogy épp a közepébe lövünk pontszerű lövést feltételezve, nulla.
Ismétlem, nulla a valószínűsége, de nem lehetetlen esemény! Mi
lesz akkor az információ tartalma ennek a közlésnek, hogy a
közepébe lőttünk?
Megnézve a képletet, az első alakot nem tudjuk használni, mert
nullával kellene osztanunk, viszont a második alakban nullának
kellene meghatározni a logaritmusát, ami ismét kudarchoz vezet.
43
Az információ képlete
A képlet tulajdonságai
Nem tudnánk kiszámolni az információ tartalmat? De, csak éppen
egy érdekes dologgal állunk szemben (már megint, ugye milyen
izgalmas ez a terület?). Határértékekkel számolva azt mondhatjuk,
hogy egy osztva nullával egyenlő végtelen, aminek a logaritmusa
szintén végtelen, s így azt kapjuk, hogy végtelen nagy az
információ tartalom, ami igaz is, hiszen végtelen sok pontból
találtunk meg az információ alapján egyet. Talán elegendő volt ez
a két példa ahhoz, hogy lássuk, milyen hasznos képletre tettünk
szert. Nézzük még meg, hogy ha egy esemény valószínűsége
50%, az mekkora információt fog jelenteni számunkra. 0.5
reciproka 2, aminek logaritmusa 1. Tehát teljesült a b. pontban
megadott feltételünk, amit követelményként támasztottunk a
képlettel szemben. Még egy példát nézzünk, s meglátjuk, milyen
kényelmes ez az összefüggés.
Mennyi az információ tartalma annak, ha egy magyarkártya
pakliból megnevezek egy lapot? A valószínűség, mivel 32 lapból
áll a csomag, 1/32. Ennek reciproka 32, aminek logaritmusa 5. Mit
mutat ez a szám? Azt, hogy ügyes kérdezéssel (az ügyes fogalmát
tisztáztuk fentebb) 5 kérdéssel tudnám kideríteni ennek a lapnak
az értékét.
1.2 Az entrópia
Fontos jellemzője még egy rendszernek az átlagos információ
tartalma. Ezt úgy lehet kiszámolni, hogy vesszük az egyes
események információ tartalmát, megszorozzuk a hozzátartozó
valószínűséggel, s összeadjuk őket. Feltehetjük, hogy nincs nulla
valószínűség, s az összes valószínűség összege egyenlő eggyel,
azaz minden esemény különálló és együtt lefednek minden
lehetséges eseményt. Ebben az esetben az információ átlaga,
vagy más szóval várható értéke:
H(X)=p1*log(1/p1)+…+ pn*log(1/pn),
amit szokás entrópiának is nevezni. A legenda szerint amikor
Weaver megalkotta ezt a képletet, nem tudta, hogy miként
44
Az entrópia fogalma és képlete
Annak a valószínűsége, hogy az Ön családneve kihal, 100%, azaz biztos esemény. Vajon miért?
nevezze el, ekkor ajánlotta Neumann János, hogy hívja
entrópiának, mert azt igazán senki sem tudja, hogy az mi, valamint
divatos belőle előadást tartani, s kérdezni úgysem mer majd senki
sem róla. Hogy ez igaz-e vagy sem, nem tudni, de entrópia néven
vonult be a tudományba ez a fogalom.
Az entrópia akkor lesz maximális, ha minden esemény
valószínűségeivel X={0.25; 0.125; 0.5; 0.125}. Számolja ki az
entrópiát, redundanciát, szórásnégyzetet!
2. Számábrázolás
2.1 A számok és a számítógép
A számítógép, ahogy a neve is mutatja, számításokra való, illetve
ez volt az elsődleges cél, amikor létrehozták. Minden feladatot úgy
végez el, hogy számolnia kell, és gyorsaságát is úgy tudjuk az
egyik legegzaktabb módszerrel lemérni, hogy megnézzük, milyen
gyorsan old meg egy bonyolult számítási feladatot. Általában
mátrixszorzásra, vagy prímszámkeresésre alapulnak a legtöbb
teszt programok. Mindenképpen számokkal dolgozik, s valahogy
ezeket a számokat tárolnia kell. Ebben a részben
megismerkedünk a legsűrűbben előforduló számábrázolási
technikákkal. A programozás során nem találkozunk közvetlenül
ezekkel az ábrázolási módokkal, a gép elrejti előlünk, de ha
alaposabban körbe akarunk járni egy problémát, vagy le akarunk
nyúlni a gépi szintre, feltétlenül ismernünk kell, mert meglepetések
érhetnek bennünket. Csak néhány olyan terület, ahol kénytelenek
vagyunk használni:
–egérkezelés
–a lemez közvetlen kiolvasása
–a rendszeridő alacsony szintű kezelése
Vagy a legérdekesebbet említve, szükségünk van rá akkor is, ha
valamilyen ok miatt tönkre megy a számítógép, s nem tudnak rajta
futni a magas szintű diagnosztizáló programok, csak a
legegyszerűbbek.
A számok fajtái számítástechnikai szempontból:
Természetes 0; 1; 2; 3; 4;…
Egész 0; -1; 1; -2; 2; -3; 3;….
Valós 0; 0.5; 2; -3.18; 0.33333, -45,3
Kicsit eltér a matematikai fogalomkörtől, mert nem különbözteti
meg a racionális, irracionális számokat. Valójában nincs is igazi
48
Számok felosztása
valós szám, mivel a számokat csak kötött számú számjegy
pontossággal és kötött intervallumban tudja ábrázolni. Ez adja a
különböző ábrázolási módok jogszerűségét. Elmondható, hogy a
számítógép a következőképpen ábrázol:
–A természetes számokat kettes számrendszerbeli alakjukkal–A negatív egészszámokat kettes komplemenssel–A valós számokat pedig lebegő pontos számábrázolással.Az első két ábrázolási módot fixpontos ábrázolásnak is nevezik,
ami arra utal, hogy a kettedes pont helye fix, míg a
lebegőpontosnál változik a kettedes pont helyzete. Valós
számokat is tudunk fixpontosan ábrázolni, de nem annyira
elterjedt.
2.2 Helyiértékes számábrázolás, számrendszerek
Mielőtt konkrétan megnézzük az ábrázolási módokat, figyeljük
meg a számok írását:
124.16Egy számnak két részét különböztetjük meg, a tizedespont előtti
részt egész résznek nevezzük, a tizedespont mögöttit
törtrésznek. A példában jól látszik az is, hogy fontos szerepet tölt
be a tizedesponttól való távolság és irány valamint a számjegy
nagysága. Általánosan felírva egy számot, a következőképpen
számolhatjuk ki az értékét:
ABC.DEFJelentse p a számrendszer alapszámát, mely az előző példában
10 volt. Ha a számjegy balra foglal helyet az egész és törtrészt
elválasztó ponttól, akkor az általa képviselt érték a számjegy
szorozva ptávolság-1-gyel. Tehát esetünkben a B által képviselt érték
B*101. C esetében C*100=C*1.
Ha a számjegy jobbra foglal helyet az egész és törtrészt elválasztó
ponttól, akkor az általa képviselt érték a számjegy szorozva
p–távolság-gal. Tehát esetünkben az E által képviselt érték E*10–2. D
esetében D*10–1. A szám által képviselt teljes értéket megkapjuk,
ha összeadjuk a számjegyek által képviselt értékeket:
49
Számítástechnikai és matematikai számfogalom különbségek
Fixpontos ábrázolás
Az ABC.DEF értéke: A*102+B*101+C*1+D*10–1+E*10–2 +F*10–3
=A*100+B*10+C*1+D*0.1+E*0.01+F*0.001
Az első példa esetén:
124.16= 1*102+2*101+4*1+1*10–1+6*10–2=
=1*100+2*10+4*1+1*0.1+6*0.01
2.2.1 Konvertálás tízes számrendszerbe
Ezekben a példákban 10 hatványaival számoltunk, de szinte
tetszőleges szám hatványaival számolhatnánk, s ezt a számot
nevezzük a számrendszer alapjának. A számrendszer alapja
mindig pozitív egész szám, de természetesen ki lehet terjeszteni
más számkörökre is a számrendszer fogalmát. Ha p a
számrendszer alapja, akkor p féle számjegyünk van, s ezek rendre
0; 1; 2;…; p-1.Tehát például a hatos számrendszer számjegyei: 0; 1; 2; 3; 4; 5.
A tizenhatosé:1; 2; 3; 4; 5; 6; 7; 8; 9; A; B; C; D; E; F, ahol
Betűjel Érték
A 10
B 11
C 12
D 13
E 14
F 15
Amíg nem szokjuk meg, addig érdemes felírni ezt a kis segéd
táblázatot.
Számoljuk ki A4F.5B16 értékét! Az alsó indexben szereplő 16-os
szám mutatja a számrendszer alapját, ezt mindig kiírjuk a
továbbiakban. Ha nem szerepel, az azt jelenti, hogy tízes
általában úgy konvertálunk, hogy először tízesbe átalakítjuk a
számot, majd onnan alakítjuk át a cél számrendszerbe.
2.2.3 Egyszerűsített konvertálások
Néha mégis van lehetőségünk arra, hogy elkerüljük ezt a dupla
utat. Az alkalmazhatóság feltétele az, hogy a kiinduló
számrendszer alapja egészhatványa legyen a cél
számrendszernek. Ilyen például a kettes és a nyolcas, vagy a
hetes és a negyvenkilences számrendszerek. Ekkor összefogunk
annyi számjegyet az alacsonyabb számrendszerbeli számnál,
ahanyadik hatványa a magasabb alapja a kisebbnek, majd ezeket
a csoportokat írjuk át. Tehát ha például kettesből akarunk
nyolcasba írni, akkor 3 számjegyet fogunk össze az egész és a
tört részt elválasztó ponttól kezdve. Ha kevesebb a számjegyek
száma az utolsó csoportban, akkor kiegészítjük nullákkal. Lássunk
2 példát!
Adott az 11011.112 szám, írjuk át nyolcasba! Először kiegészítjük
úgy, hogy a számjegyek száma mind a tört, mind az egész
részben osztható legyen hárommal, mert 3 kettes
számrendszerbeli számjegy ad ki egy nyolcas számrendszerbelit
(kettő a harmadikon egyenlő nyolc):
011 011. 110, ezek után átírjuk a csoportokat:
Az első csoport:0112, azaz 3, ami egyenlő 38
A második csoport:0112, azaz 3, ami egyenlő 38
Az harmadik csoport:1102, azaz 6, ami egyenlő 68
Ezeket egymás mellé írva alakul ki 33.68 alak. Visszafelé ugyanígy
járunk el, csak majd a vezető és utolsó nullákat kell kitörölni a
számból:
55
Tetszőleges konvertálások
Nézzünk egy példát, ahol 16-os számrendszerből írunk át
kettesbe:
3A2F.3B416
Határozzuk meg először a csoportokban résztvevő jegyek számát:
kettő a negyediken egyenlő 16, így négy jegybe kell átírni
egyenként a 16-os számrendszerbeli jegyeket:
3 --- 0011
A --- 1010
2 --- 0010
F --- 1111
3 --- 0011
B --- 1011
4 --- 0100
Egymás mellé írva a csoportokat:
0011 1010 0010 1111. 0011 1011 0100
Töröljük ki a felesleges nullákat, s készen is vagyunk:
3A2F.3B416=11 1010 0010 1111. 0011 1011 012
2.2.4 A pontosság korlátjai
Sokszor felvetődik, hogy el kell dönteni, mekkora a legnagyobb és
a legkisebb (nem nulla) szám egy adott számrendszerben, ha
ismerjük a törtrész és az egészrész számjegyeinek a számát.
Legyenek ezeknek számai B és A. A legkisebb szám nyilván az
lesz, melynek minden jegye nulla, csak a törtrész utolsó
számjegye egyes. Ha a törtrész B darab számjegyet tartalmaz, és
56
Gyakorló feladat: Számok megadása, konvertálása „rokon”
számrendszerek között:
Írja hármasból 9-esbe, 16-osból kettesbe: 221
Írja kilencesből hármasba: 221
Írja tizenhatosba kettesből: 100100101101
A legnagyobb és a legkisebb szám
p a számrendszer alapszáma, akkor ennek az értéke p-B. A
legnagyobb szám pedig nem más, mint egy olyan szám, ahol
minden jegyen a lehető legnagyobb számjegy áll, ami p alapú
számrendszerben épp a p-1. Ekkor, ha hozzáadnánk az imént
ismertetett legkisebb számot, folyamatos túlcsordulásokkal egy
olyan számot kapunk, amelynek első jegye egyes, a többi nulla, s
ez az első jegy most jött létre az A+1. helyen.
Ezek szerint az eredeti szám pA-p-B. Nézzünk erre is példát!
Legyen A=5, B=3, tehát az egészrész számjegyeinek száma 5, a
törtrész számjegyeinek száma 3. A számunk legyen négyes
számrendszerben. Ekkor a legkisebb (nem nulla) számunk alakja:
00000.0014
Kiírtuk a vezető nullákat, hogy jobban látszódjon az eredeti szám.
Valóban ennek értéke 4-3. A legnagyobb számunk:
33333.3334, melyhez hozzáadva az iménti 0.0014 számot kapjuk,
hogy 100000.000. Emiatt a legnagyobb számunk értéke 45-4-3
Speciálisan, ha nincs törtrész, akkor B=0, tehát pA-p0=pA-1 a
legnagyobb szám értéke.
2.3 Pozitív számok ábrázolása fixpontosan
Térjünk rá a fejezet egyik fő céljára, a számábrázolásra.
Említettük, hogy a természetes számokat kettes számrendszerbeli
57
Gyakorló feladat: Határozza meg a következő esetekben a
szám pontosságát, a legkisebb és legnagyobb számot:
Hatos számrendszerben 4+2 jegyen
Kettesben 3+1 jegyen
Tizenhatosban 2+2 jegyen
Négyesben 5 jegyen
Hármasban 3 jegyen
Számábrázolás
alakjukkal ábrázoljuk. A feladat egy kicsit tér csak el az eddig
ismertetett számrendszer átírásoktól, mégpedig annyiban, hogy itt
pontosan megmondjuk, hogy mennyi helyünk van egy-egy adat
számára, azaz minden esetben ki kell töltenünk az esetleg vezető
nullákat is. Amikor számábrázolásról beszélünk, mindig
megmondjuk, hogy hány biten történik. Általában ez a
számítógépek byte alapú memória szervezése miatt 8-nak valamely egész számú többszöröse lesz. Ettől persze a
feladatokban el lehet térni, de a gyakorlatban mindig valahány
byte-on ábrázoljuk a számokat.
Nézzünk azért egy példát:
Adjuk meg a 8 biten a hetvenhármas szám alakját!
73=010010012
Amennyiben elképzelünk egy kettedes pontot is a számban,
lehetőségünk van valós számok ábrázolására. Ilyenkor az első
bitet az előjelnek tartjuk fent, amennyiben értéke nulla, pozitív lesz
a számunk, egyes esetén negatív. Nem terjedt el a gyakorlatban,
de néhány programozási nyelv alkalmazza. Erre is nézzünk két
példát:
Legyen az ábrázolni kívánt számunk a 9.75, a kettedes pontot
jobbról számolva a 3. bit elé képzeljük el. Ekkor számunk a
következő alakot nyeri kettes számrendszerben:1001.112
Ábrázoljuk 16 biten: az első bit 0, mivel pozitív a szám. Ki kell
egészíteni még a végét egy nullával, hogy megfelelő helyre
kerüljön a kettedes pont:
0000 0000 0100 1110
A második példa legyen a –121.32. Ekkor a szám bináris alakja:
1111001.010100011…2
Legyen a kettedes pont jobbról a 6.bit előtt, így mivel a szám
negatív, első bitje egyes, és lecsonkoljuk a végét úgy, hogy csak 6
értékes jegy maradjon a törtrészben. Az ábrázolt 16 bites érték:
1001 1110 0101 0100
58
2.4 Negatív számok ábrázolása fixpontosan
Egész számok esetében az a gond, hogy lehet negatív is egy
szám. Célszerűnek látszik fenntartani egy bitet –mondjuk az elsőt–
ennek jelölésére, de a gyakorlatban más módszer vált be,
mégpedig a kettes komplemenssel való ábrázolás. Ismerkedjünk
meg ennek a fogalmával. A komplemens, mint idegen szó azt
jelenti, hogy kiegészítő. Valóban, a kettes komplemens is ezt
jelenti, nem a számot ábrázoljuk, hanem azt az értéket, mely
kiegészíti az ábrázolható legnagyobb számra. Figyeljük meg a
következő egyszerű trükköt, ami miatt bevezették a kettes
komplemens használatát:
Tegyük fel, hogy ki akarjuk vonni 563-ból a 452-t. Ezt így is el lehet
végezni:
563+(1000-452)-1000
Látszólag feleslegesen bonyolítottuk meg a dolgot, de a
számítógépen nagyon könnyű egy egész hatvány kivonása, hiszen
csak el kell hagyni az első számjegyet:
13-8=11012-10002=01012 Látható, hogy ugyanerre jutottunk volna,
ha elhagyjuk az 11012 számból az első egyest. A komplemens
képzéssel azt érjük el, hogy nem a –452-t ábrázoljuk, hanem az
1000-452-t. Így, ha összeadjuk valamely számmal, s elhagyjuk az
első számjegyet, helyes eredményt kapunk:
1000-452=548Ezt a kivonást is könnyebbé tehetjük, ha észrevesszük, hogy
1000-452=1+999-452
59
Kettes komplemens
Gyakorló feladat:
Adja meg 13 és 25 értékét 8 biten
Adja meg 11.75 és 19.125 értékét 8 biten, ha a kettedes pont
jobbról a 3. jegy előtt van
Ennek az összegnek a 999-452 része nagyon könnyen
számolható, hiszen megkapjuk az eredményt, ha a szám minden
jegyét kiegészítjük kilencesre, ezt hívjuk kilences komplemensnek:
452 kilences komplemense 547, mert ez az a szám, melynek
jegyei épp kilencre egészítik ki a 452-es számot. Az 547-hez
hozzáadva 1-t, megkapjuk az eredeti 548-ast, ami a cél volt. Ezt
szokták nevezni tízes komplemensnek is néha.
Ezek szerint:
563-452==563+548-1000==1111-1000=111.
Valóban, 563-452=111.
Nézzük meg egy másik példán, de már kettes számrendszerben.
Végezzük el 5 biten a 8-3 műveletet:
8 alakja 5 biten kettes számrendszerben: 01000
3-at az iménti módszerrel ábrázoljuk, először meghatározzuk az
egyes komplemensét, azaz minden bitjét kiegészítünk egyesre.
Ez kettes számrendszer esetén nagyon egyszerű, ahol egyes van oda nullát, ahol nulla van, oda egyest kell írni:A 3 alakja kettes számrendszerben 5 biten: 00011, ennek egyes
komplemense: 11100. Adjunk még hozzá egyet, így kapjuk meg a
kettes komplemenst: 11101
Most már ezt a számot hozzáadva a 8-hoz és elhagyva az első –
túlcsordulással létrejött számjegyet, megkapjuk az eredményt:
8+(-3)=01000+11101=1|00101, elhagyva a vonal előtti jegyet
00101-et kapunk, melyet visszaszámolva 5 az eredmény.
Negatív számokat kettes komplemenssel ábrázoljuk, mintegy
előkészítve arra a számot, hogy megtörténjen a kivonása az
abszolút értékének, tehát a szám hozzáadása valamely számhoz.
Vegyük észre, hogy így nincs szükség a kivonás műveletére, elég,
ha a processzor csak összeadni tud. Az egyes komplemens
képzése nagyon egyszerű a gépnek, minden bit helyére az
ellentettjét írja, majd az első jegy elhagyása is könnyű, mert az
60
Egyes komplemens
általában egyszerűen elveszik, ha nincs hely a tárolására
(valójában a FLAG regiszter ún. átvitelt jelző bitjébe csúszik át).
Ennél az ábrázolási módnál az a csel, hogy a szám előjelét
elrejtjük az utolsó számjegy kódjában, a többi számjegy kódja
marad ugyanaz, mint eddig, tehát a számjegyhez tartozó ASCII
kód. Láthattuk, hogy erre lehetőség van, hiszen elég lenne a fél
bájt is a számjegy ábrázolására. Kétfajta ábrázolás terjedt el, az
egyiket nem túl találóan első a másikat második zónás
ábrázolásnak nevezik. Az alábbi táblázatban megadjuk mindkét
esetben (azaz amikor a szám pozitív illetve negatív) az utolsó
számjegyhez tartozó bájt kódját. Figyeljük meg, hogy az első
67
Az előjel bájtos decimális számábrázolás
Gyakorló feladat: Adjuk meg 143 és –56 alakját!
Beépített előjeles decimális ábrázolás
zónás esetben pozitív számok esetén nincs különösebb furfang,
negatív számok esetén is csak a fél bájt értéke változik. A második
zónás ábrázolásban kissé bonyolultabb a helyzet, de nem
reménytelen, ha észrevesszük, hogy a számjegyek értékei
növekvő sorrendben vannak, kivéve a 0-hoz tartozó kódokat.
Tehát a táblázat:
Az előjel Az utolsóSzámjegy
Első zónásKód
Második zónásKód
+ 0 30 7B
+ 1 31 41
+ 2 32 42
+ 3 33 43
+ 4 34 44
+ 5 35 45
+ 6 36 46
+ 7 37 47
+ 8 38 48
+ 9 39 49
– 0 70 7D
– 1 71 4A
– 2 72 4B
– 3 73 4C
– 4 74 4D
– 5 75 4E
– 6 76 4F
– 7 77 50
– 8 78 51
– 9 79 52
68
Az előjel tárolása fél bájton
Nézzünk két példát, s mindegyiknek mindkét kódolási megfelelőjét.
Legyen a számunk a –267. Ennek alakja az első zónás
formátumban 32 36 77. A 3216 és 3616 jelzi az első két számjegyet,
a kettest és a hatost. A 7716 jelentése a fenti táblázat 3. oszlopából
kiolvasható, tehát az utolsó számjegy hetes, és a szám negatív.
Második zónásan ugyanez a szám: 32 36 50. Az első két rész
értelmezése ugyanaz, mint az első zónás ábrázolásnál, az 5016
értelmezése szintén kiolvasható a táblázatunk 4. oszlopából, tehát
az utolsó számjegy hetes, és a szám negatív.
A következő számunk legyen a 3267.
Ennek alakja az első zónás formátumban 33 32 36 37. A számok
értelmezése:
3316––3, 3216––2, 3616––6, 3716––7, és mivel ez az utolsó
számjegy, tudjuk, hogy a szám pozitív a táblázat 3. oszlopa miatt.
A második zónás alakja a számnak 33 32 36 47, a számok
értelmezése:
3316––3, 3216––2, 3616––6, 4716––7, és mivel ez az utolsó
számjegy, tudjuk, hogy a szám pozitív a táblázat 4. oszlopa miatt.
Megfigyelhetjük, hogy mind az első, mind a második zónás
számábrázolásnál ugyanannyi bájtot használunk a számjegyek
ábrázolására, mint ahány számjegy van, mert az előjel beépül az
utolsó számjegyet ábrázoló bájtba. Ez csekély javulás a külön
előjel bájttal való ábrázoláshoz képest, az igazi áttörést a
következő ábrázolási forma adja:
2.6.3 Tömörített ASCII kódú ábrázolás
Ennek az ábrázolási formának az elterjedt elnevezése a BCD
(Binárisan kódolt decimális szám) Említettük már, hogy pazarlás
egy teljes bájtot alkalmazni egyetlen számjegy ábrázolására, ez a
69
Gyakorló feladat: Adja meg 143 és –56 alakját beépített
előjel bájttal mindkét zónás ábrázolásban!
Az ábrázolás gazdaságossága
kódolás oldja meg a problémát, ugyanis két számjegyet sűrít egy
bájtba, egyiket az első, másikat a második felére helyezve el. Az
előjel az utolsó fél bájtra kerül oly módon, hogy a C16 a „+” jelet a
D16 a „–” jelet fogja jelenteni. A számjegyeknek a saját értéküknek
megfelelő hexadecimális szám kerül, ami pontosan megegyezik a
számmal, ez biztosítja azt, hogy könnyű kiíratni őket. Van egy kis
gond, mégpedig az, hogy a számítógépek bájt szervezésűek, ami
azt jelenti, hogy nem illik fél bájtra helyezni egy adatot. Mivel a
számunknak egy bájt egész számú többszörösének kell lennie a
tárolóban, ezért úgy oldották meg, hogy egyszerűen elé írnak egy
nullát, ha nem így lenne. Mikor fordul elő ez a gond? Mivel minden
számjegy fél bájtot foglal el, és még az előjelnek is kell egy fél bájt,
ezért ha a számunk páros számú számjegyet tartalmaz, akkor
szükséges ez a kiegészítés. Ismét lássunk 2 példát:
Legyen a számunk a –123. A szám páratlan számjegyből áll,
emiatt nem kell kiegészíteni az elején egy nullával, hanem már
kódolhatjuk is: 12 3D.
A 1216 jelenti az egyes és a kettes számjegyet, a 3D16 a hármast
és a negatív előjelet, azaz 316 miatt a hármas és a D16 jelzi, hogy
negatív a számunk.
Nézzük meg a +127 kódolását, mivel a szám páratlan számjegyből
áll, emiatt nem kell kiegészíteni az elején egy nullával, így az
eredmény: 12 7C.
1216 jelenti az egyes és a kettes számjegyet, a 7C16 a hetest és a
pozitív előjelet, azaz 716 miatt a hetes és a C16 jelzi, hogy pozitív a
számunk.
Nézzünk egy példát arra is, amikor ki kell egészíteni a számot
nullával, azaz páros számú számjegyet tartalmaz:-5462.
Ekkor a kódolás előtt eléírunk egy nullát: –05462. Így már átírható,
a megoldás: 05 46 2D. A D16 jelzi a negatív tulajdonságot, s
látható, hogy ha nem lenne kiegészítve nullával az elején, akkor
bizony ott maradt volna egy bájt befejezetlenül.
70
Gyakorló feladat: Adjuk meg 143 és –56 alakját tömörített
ábrázolásban!
A fentieken kívül léteznek még más kódrendszerek is, de a
logikájuk nagyban megegyezik az ismertetettekkel. Ilyen kódolás
például az amikor a karaktereket az EBCDIC kódjukkal írjuk le, de
napjainkban már nem használják széles körben ezt a
kódrendszert, ezért választottuk a tárgyalás alapjául az ASCII
kódú decimális ábrázolásokat.
3. Logikai adat, karakter, sztring ábrázolás
3.1 Logikai adat
A logikai adat fogalma egyszerű, ahogy az ábrázolása is. A
világunk logikailag két részre osztható, úgynevezett kétértékű
világban élünk, egy állítás vagy hamis, vagy igaz. Ha azt állítjuk,
hogy esik az eső, akkor az vagy igaz, vagy hamis, nem
mondhatjuk, hogy esik is meg nem is, az adott pillanatban vagy
esik, vagy nem. Számítástechnikában ezt a két értéket igaznak és
hamisnak nevezzük, használatos még a true és a false kifejezés
is, ami az angol megfelelője. Ábrázolni elég egy bit, hiszen 2
állapota van, a nulla és az egyes. A nullával szokás a hamisat, egyessel az igazat jelölni. A gyakorlatban a fentebb említett bájt
szervezés miatt mégis egy bájtot használnak, de ez erősen
programozási nyelv függő, a legalacsonyabb, leggépközelibb
nyelven egy biten ábrázolják ezt a két állapotot.
3.1.1 Logikai műveletek és igazság tábláik
A logikai adatoknál sokkal érdekesebbek a velük végezhető
műveletek. A legsűrűbben használt műveletek a következők:
NOT ––- tagadás műveleteAND ––- logikai és műveletOR ––-– logikai vagy műveletXOR––– logikai kizáró vagy műveleteA későbbiekben megadjuk az összes lehetséges műveletet. A
műveletek megadása úgynevezett igazság táblákkal történik,
71
Egyéb kód rendszerek
A logikai adat
Logikai művelet
ezekből tudjuk leolvasni a műveletek eredményét, hasonlóan
használhatjuk, mint kisiskolás korunkban a szorzótáblát. Nézzük
meg például a logikai és igazság tábláját:
AND 1 0
1 1 0
0 0 0
A tábla használata egyszerű, a művelet egyik tagját kikeressük az
első oszlopból, a másik tagját az első sorból, s a kettő metszete
adja a művelet eredményét. Hosszabban írva a logikai és „szorzó
táblája”:
1 AND 1 = 1
1 AND 0 = 0
0 AND 1 = 0
0 AND 0 = 0
Látható, hogy rövidebb és gyorsabb az igazság tábla használata.
Megegyezünk, hogy a művelet első tagját az első oszlopból, a
másodikat pedig az első sorból vesszük. A fenti példánál ez nem
okoz gondot, mert a logikai és úgynevezett kommutatív művelet,
ami azt jelenti, hogy az operandusok felcserélhetőek, s az
eredmény ugyanaz marad.
Figyeljük meg, hogy nem véletlen a logikai és elnevezése, ugyanis
ha egy lány okos és szép, akkor a következő állításokat tehetjük, s
az állítások igazságtartalma a következőképpen alakul:
A lány okos és szép ––––––> igaz állítás
A lány okos és csúnya ––––> hamis állítás
A lány buta és szép ––––––> hamis állítás
A lány buta és csúnya ––––> hamis állítás
Összehasonlítva ezt az igazság tábla hosszabb leírásával, a
szépnek és az okosnak egyest, a csúnyának és a butának nullát
feleltetve meg, szembeötlő a hasonlóság.
72
Az igazság tábla
A következőben megadjuk a műveletek igazság tábláit:
AND 1 0
1 1 0
0 0 0
OR 1 0
1 1 1
0 1 0
XOR 1 0
1 0 1
0 1 0
A logikai vagy azt hiszem, nem szorul magyarázatra, a kizáró vagy
pedig a magyar nyelvben ismert, például a következő mondatban:
Pénzt, vagy életet!
Tehát akkor igaz, ha vagy pénzt, vagy életet adunk, de a kettőt
együtt nem követelik, ahogy azzal sincsenek megelégedve, ha
egyikkel sem szolgálunk.
Az igazság az, hogy a magyar nyelvben a kizáró vagyot
használjuk inkább, de például ha egy házassághirdetésben azt
olvassuk, hogy fiatal legyen a partner vagy gazdag, nyilván nem
záródik ki az a szerencsés eset sem, amikor mindkettő teljesül, és
csak azoknak nem érdemes jelentkezni, akik öregek és
szegények.
Kimaradt a tagadás igazság táblája, mivel az egy kicsit eltér a
többitől amiatt, hogy egy operandusú művelet, tehát csak egyetlen
tagja van. Az igaz ellentettje a hamis, és a hamis ellentettje az
igaz. Az igazság tábla ezért a következő alakot ölti:
NOT
1 0
0 1
73
Nem csak ez a négy művelet van, de ezek a leginkább használtak
a számítástechnika berkein belül. Hogy teljes legyen a
felsorolásuk, megadjuk a többit is, de ezekkel nem foglalkozunk
bővebben:
Az első két logikai függvény igazság táblája igazából nem is
érdekes, egyik a konstans igaz, a másik a konstans hamist adja,
azaz nem függ attól a művelet eredménye, hogy mi a két változó
értéke:
Az igaz tábla:
True 1 0
1 1 1
0 1 1
Az hamis tábla:
False 1 0
1 0 0
0 0 0
A következő tábla értéke csak az első elemtől függ, azonos vele:
Az A tábla:
A 1 0
1 1 1
0 0 0
A következő tábla értéke csak az első elemtől függ, ellentétes
vele:
A NOT(A) tábla:
NOT(A) 1 0
1 0 0
0 1 1
74
A következő táblák B-re valósítják meg ugyanezt:
A B tábla:
B 1 0
1 1 0
0 1 0
A NOT(B) tábla:
NOT(B) 1 0
1 0 1
0 0 1
A fenti 4 tábla egyváltozós függvénynek is tekinthető, mivel csak
az egyik változó játszik szerepet benne.
Az AND, OR, XOR táblákat már megadtuk, adjuk meg ezek
negáltjait is!
A NOT(A AND B) tábla (NAND):
NAND 1 0
1 0 1
0 1 1
A NOT(A OR B) tábla (NOR):
NOR 1 0
1 0 0
0 0 1
A NOT(A XOR B) tábla (XNOR):
XNOR 1 0
1 1 0
0 0 1
Tudjuk, hogy az igazság tábla 4 mezőjén helyezkednek el az
értékek, s mivel mindegyik 2 állapotot vehet fel, ezért 24 változat
75
lehetséges, tehát 16. Hogy teljes legyen a felsorolás, megadjuk a
még hiányzó négy igazság táblát is:
Az A B tábla (A implikáció B):
A B 1 0
1 1 0
0 1 1
Az B A tábla (B implikáció A):
BA 1 0
1 1 1
0 0 1
Az A inh B tábla (A inhibíció B):
A inh B 1 0
1 0 1
0 0 0
Az B inh A tábla (B inhibíció A):
B inh A 1 0
1 0 0
0 1 0
Végezetül soroljuk fel mind a 16 lehetőséget:
Igaz, hamis, A, Not A, B, Not B, And, Nand, Or, Nor, Xor, Xnor, és
a 4 művelet, ahol számít a tagok sorrendje, tehát nem
kommutatívak: B A, A B, A inh B, B inh A
Az implikáció következményt jelent, az inhibíció pedig tiltást.
3.1.2 Logika és halmaz
A logikai műveletek szoros kapcsolatban állnak a halmazokkal,
ezért szokás azonosítani őket halmaz műveletekkel is. A logikai és
a halmazoknál a metszetnek felel meg, hiszen ha egy elem benne
van egy A halmazban és egy B halmazban, az benne van a két
76
Lehetséges műveletek
Halmazokkal való kapcsolatuk
halmaz metszetében is. Mivel a metszetet két halmaz esetén a
szorzás jellel jelöljük, ezért szokás használni a logikai és jelölésére
a szorzás jel is.
A logikai vagy-nak az unió felel meg, hiszen ha egy elem benne
van egy A halmazban vagy egy B halmazban, akkor benne van a
két halmaz uniójában. Az unió jele az összeadás, így a logikai
vagy-ot szokás összeadás jellel is jelölni. Mivel számítástechnikai
oldalról közelítjük most meg a problémát, mi maradunk a
hagyományos angol elnevezéseknél.
3.1.3 Fixpontos számok logikai műveletei
Sokkal izgalmasabb esettel állunk szemben, amikor a logikai
adatokat egy bitnek tekintve kettes számrendszerbeli számokra
alkalmazzuk a fenti műveleteket. Ezt nyugodtan megtehetjük, s
használják is elég sűrűn a programozási gyakorlatban, a
műveletek neve ilyenkor bitenkénti NOT, bitenkénti OR és így
tovább. Nézzünk erre egy példát!
Számoljuk ki a 4 OR 6 eredményét! Megegyezhetünk, hogy a
számokat 8 biten ábrázoljuk, ebben az esetben
4=0000 01002,
6=0000 01102
Végezzük el a logikai műveletet úgy, hogy az egymás alatt lévő
bitekre alkalmazzuk, tehát például az eredmény 5. bitje egyenlő a
4 kettes számrendszerbeli alakjában az 5. bit és a 6 bináris
alakjában az 5. bit logikai vagy műveletének az eredménye.
Ekkor a következőhöz jutunk:
0000 01002=4
0000 01102=6
0000 01102=6
Ily módon nagyon jól lehet gyakorolni a logikai műveletek
elvégzését, de nézzünk egy-két érdekes dolgot.
Ha egy N számnak kíváncsiak vagyunk az 5. bitjére, akkor ezt
kinyerhetjük a következő módon: (N AND 16) / 16, ugyanis ha a
számot bitenként AND kapcsolatba hozzuk a 16=0001 00002
77
Próbálja megadni az összes műveletet csak negáció, AND és OR műveletekkel!
Logikai műveletek számokkal
számmal, akkor láthatjuk, hogy csak az 5. bitje marad meg, így a
művelet értéke 16 lesz, ha a szám kérdéses bitje egyes volt és
nulla, ha nulla volt. Ezt elosztva nyilván vagy egyet, vagy nullát
kapunk, ami szolgáltatja a kívánt eredményt. Egy másik
alkalmazási terület, amikor gyorsan akarunk kinullázni egy bájtot,
azaz nullává tenni. Ilyenkor a megoldást az N XOR N szolgáltatja,
mivel önmagával vett XOR művelet nullát ad, ha megfigyeljük az
igazság táblában azt, hogy 1 XOR 1= 0 és 0 XOR 0= 0.
3.2 A karakter adat
3.2.1 Karakterek osztályozása
A karakterekről már volt szó az ASCII kódtábla esetén, nézzük
meg, milyen osztályokba sorolhatjuk a karaktereket.
a. Alfanumerikus jelek
Idetartoznak a betűk és a számok. Hagyományosan minden
karakterkészletben benne vannak az angol ábécé kis és nagy
betűi, ez 26-26 jelet eredményez, a szóköz (space) valamint
nullától kilencig a számjegyek. Jellemző az is, hogy szoftveres
úton megoldják a nemzeti karakterek ábrázolását is, tehát pl.
Magyarországon a karakterkészletben megtalálhatóak azon
magyar karakterek, melyek nincsenek benne az angol
ábécében. Ha meg akarjuk nézni, hogy valóban megvan
minden karakter ezen betűk közül, nagyon jó szolgálatot tesz,
ha megjegyezzük a következő szót:
árvíztűrőtükörfúrógépEz azért szerencsés szó, mert mindenkaraktert tartalmaz,
amelyik nincs benne az angol ábécében.
78
Gyakorló feladat: Értékelje ki a (true and not true)or
(false or true) kifejezést
Mennyi (3 and 2 ) or 1 négy biten?
Karakterek osztályozása
b. Írásjelek
Idesoroljuk a vesszőt, pontot, pontos vesszőt, kérdőjelet, és
így tovább, tehát minden olyan írásjelet, melyet használunk
írás közben, valamint a különböző zárójeleket, az aposztrófot,
az idéző jelet.
c. Matematikai műveleti jelek
Ezek a hagyományos műveleti jelek, mint az összeadás jele
„+”, kivonás, szorzás esetén a csillag, osztásra a „/” jel
használatos. Idetartoznak még a relációs jelek, mint pl. az =; >;
<.
d. Grafikai jelek
Olyan jeleket tartalmaz, melyet egyszerű rajzolásokhoz lehet
felhasználni, például keretek rajzolásához. Van függőleges
vonal, vízszintes, sarok készítésére alkalmas, és még
rengeteg.
e. Egyéb jelek
Ez a kategória tartalmaz minden olyan jelet, mely az
előbbiekben nem volt felsorolva. Néhányat megadunk, mivel
különleges nevük van, és kellemetlen szokás, hogy
szakemberek sem tudják a nevüket. Érdekességképpen néhol
megemlítjük, hogy milyen egyéb fantázia neveket találtak ki.
– # Hash–mark (Kettős kereszt, trágyajel)
– @ At–mark (printkukac, farkincás a)
– ~ Tilde (Kishullám, tilda)
– $ Dollár jel
– \ Back slash (Visszafele per jel)
– & Ampersand (És jel)
3.2.2 Karakterek ábrázolása
Az egy bájtos hely miatt 256 különböző karaktert lehet ábrázolni,
ez kevésnek bizonyult ahhoz, hogy minden nemzet megtalálja a
saját karaktereit közöttük. Létezik az ASCII kódtábla, mint régi és
szabványos karakter tábla, de mellette más kódtáblák, kódolások
79
Kódtáblák
is megjelentek. Jellemzője mindegyiknek, hogy 256 karaktert
tartalmaz, de ezek részben különböznek, elhagynak az eredeti
ASCII kódtáblában meglévő jeleket, hogy a saját új jelekkel
helyettesítsék. Általában a számok, betűk ugyanazzal a kóddal
szerepelnek. Ilyen kódtáblák a KOI-8, EBCDIC, DKOI.
Igazi megoldást az összevisszaságra az UNICODE tábla jelenti,
mely még kidolgozás alatt áll, azaz vannak kódok, melyekhez még
nem szabványosítottak karaktert. Azért tudja ez a kódtábla
megoldani a problémát, mert egy karaktert 2 bájton ábrázol, tehát
216=65536 féle jelet tud azonosítani. Ebbe a szakemberek szerint
minden nemzet minden karaktere belefér a magyartól kezdve a
szanszkritig.
A kód kiosztás nem összevissza történt az ASCII kódtáblánál sem,
a kódtábla elején a vezérlőjelek helyezkednek el, amikhez igazi
megjeleníthető karakterek nem tartoznak. Ilyen a sorvége jel, vagy
a printert vezérlő egyéb kódok. A számok ASCII kódjait már láttuk,
hogy szerencsésen lettek megalkotva, de ugyanez elmondható a
betűk elhelyezésére is, ha megnézzük a hexadecimális kódjait:
A––––4116––0100 00012
B––––4216––0100 00102
a––––6116––0110 00012
b––––6216––0110 00102
Láthatjuk, hogy az utolsó négy biten kiolvasható, hogy hányadik a
betű az ábécében, és csupán egy bit különbség van a betű kis és
nagybetűs változata között. Nem kell azt hiszem hangsúlyozni,
hogy milyen nagy segítség pl. akkor, ha egy csupa kisbetűs szót
nagy betűssé kell alakítani.
80
3.3 A sztring adat
3.3.1 A sztring ábrázolása
A sztring szakkifejezést magyarra lefordítani füzér, vagy láncként
szokás, pontosabban karakterfüzér, vagy karakterlánc. Láthatjuk
ezekből, hogy arról van szó, hogy karaktereket rakunk
egymásután, azaz szöveget ábrázolunk. A szöveg tehát
karakterek egymásutánisága. Fontos dolog az, hogy miként tudjuk
ábrázolni. Ábrázolás esetén egyetlen dolog szokott gondot
jelenteni, annak eldöntése, hogy a tároló egységen mekkora helyet
foglal el, meddig kell a kódoknak megfelelő karaktereket
értelmezni. Az eddigi adatoknál mindig tudtuk, hogy egy vagy
esetleg 4 bájton, a logikai adatnál pl. egy biten ábrázolunk, itt
viszont nem tudunk határt szabni, mert a szövegek különböző
hosszúak lesznek. Valami más ötlet kellett ahhoz, hogy megoldják
ezt a problémát.
Az első nem túl ötletes, amikor korlátozzuk a sztringek hosszát, és
azt mondjuk, hogy minden sztring pontosan adott számú karaktert
tartalmaz, és az ötlettelenségen kívül nyilvánvalóak a módszer
hátrányai is. Egyrészt nem tudunk tetszőleges hosszú sztringeket
kezelni, másrészt pedig feleslegesen foglalunk helyet, ha rövidebb
sztringek is elegendőek lennének. Szerencsére nem alkalmazzák
sűrűn.
A második ötlet kissé jobb, itt csak a maximális hosszat írják elő,
de rövidebbek lehetnek a sztringek, a legtöbb programozási nyelv
ezt alkalmazza. A sztring hosszát a sztring elején helyezik el,
felhasználva egy vagy több bájtot. Ha egy bájtot tartanak fent, ez
azt jelenti, hogy a sztring hossza maximálisan 255 hosszú lehet,
ha például kettőt, akkor 65535. Ilyenkor természetesen egy sztring
karakterein kívül még tárolnunk kell a sztring hosszát megadó
bájtokat is.
A harmadik igazán frappáns, ebben az esetben úgynevezett
sztring végjelet alkalmaznak, mely valamilyen speciális karakter,
81
A sztring jelentése
A sztring ábrázolásai
pl. a nulla ASCII kódú karakter. Így nincs sem minimális, sem
maximális hossz, az egyetlen gondot az jelenti, ha az adott
karaktert is szerepeltetni akarjuk a sztringben, így olvasva őt, nem
tudhatjuk, hogy vége van-e a sztringnek, vagy pedig ez a karakter
csupán egy eleme neki. Van megoldás ennek a tévedési
lehetőségnek a kivédésére is, pl. értelmezhetik úgy, hogy ha
kétszer egymás után jön a nulla kódú karakter, az rendes karaktert
jelent, ha pedig csupán egyszer, akkor sztring vége jelet. Vannak
program nyelvek, melyek ezt a megoldást alkalmazzák.
3.3.2 A sztring műveletei
Mindegy, hogy a sztring ábrázolása melyik módszerrel történik,
mindenképpen vannak ehhez az adattípushoz kötődő függvények,
Adja meg 11.75 és 19.125 értékét 8 biten, ha a kettedes pont jobbról a 3 jegy előtt van
11.75: 0101 1110
19.125: 1001 1001
Gyakorló feladat II/5:
Adja meg ketteskomplemenssel a következő számokat:
-12: 1111 0100
25: 0001 1001
-5: 1111 1011
-1: 1111 1111
Fejtse vissza a ketteskomplemenseket:
1111 0101: -11
0001 1010: 26
86
1110 1101: -19
0000 1111: 15
Gyakorló feladat II/6: Adja meg –17.625 és 123.567 lebegőpontos alakját!
-17.625: 1|10000101|00011010000000000000000
123.567: 0|10000111|11101110010001001001101
Gyakorló feladat II/7:
Adja meg 143 és –56 alakját!
143: 2B 31 34 33
-56: 2D 35 36
Gyakorló feladat II/8:
Adja meg 143 és –56 alakját beépített előjel bájttal mindkét zónás
ábrázolásban
Első zónás:
143: 31 34 33
-56: 35 76
Második zónás:
143: 31 34 43
-56: 35 4F
Gyakorló feladat II/9
Adja meg 143 és –56 alakját tömörített ábrázolásban!
143: 14 3C
-56: 05 6D
Gyakorló feladat II/10
Értékelje ki a (true and not true)or (false or true) kifejezést
True
87
Mennyi (3 and 2 ) or 1 négy biten?
3
Gyakorló feladat II/11Mely részei azonosak a kódtábláknak és miért?
A betűk, számok, írásjelek, mert mindegyikben benne vannak
Miért használnak vajon csak 7 bitet az ismeretlen rendszerek
közötti kommunikációban?
Mert az utolsó bit paritás ellenőrző, véd a hibák ellen
SMS-ben miért fordulhat elő, hogy minden karaktert megelőz egy
„@” karakter?
Ha a küldő UNICODE rendszert használ, akkor 2 bájt egy karakter,
de ha a fogadó egy bájtos rendszert használ, csak minden
második karakter értelmes
88
III. tanulási egység
AdatszerkezetekBevezetés
Az eddigi két egységben megismerkedett az algoritmussal, és az
algoritmusban használható adatok ábrázolásaival. A következő
egység elsajátítása után tisztában lesz azzal, hogy micsoda óriási
különbség van a különálló és az egymással kapcsolatban lévő
adatok között, s mennyivel hatékonyabban tudunk problémákat
megoldani az adatszerkezetek segítségével.
Először ehhez tudnunk kell, hogy miről beszélünk, tehát
ismertetjük az adatszerkezet fogalmát, majd a különböző fajtáit, a
hozzájuk kötődő főbb algoritmusokat, majd azt, hogy milyen
szerepet játszanak a számítástechnikában és a programozásban.
Az egyik legizgalmasabb dolog a keresés és a rendezés
algoritmusainak használata, használhatóságuk feltételei, egyre
gyorsabb és optimálisabb algoritmusokat nézünk meg rájuk. Az
adatszerkezeteknek is, akárcsak a számoknak, léteznek eltérő
ábrázolási módjai, ezekből is megismer néhányat.
A tanegység feladatainak elvégzése után meg tudja határozni,
hogy milyen adatszerkezettel képes megoldani valamely
problémát, a keresések, rendezések esetén több algoritmust is
ismer, s képes ezek közül kiválasztani a legmegfelelőbbet a
feladat sajátosságait figyelembe véve.
Az adatszerkezet több, mint adatok összessége, az adatok között
lévő kapcsolatok adják a pluszt. Adatszerkezeten mi a
továbbiakban a következőt értjük:
Az adatszerkezet az adatok, az őket összekötő kapcsolatokkal együtt.A legfőbb kapcsolat egy adatszerkezetben lévő adatok között
általában az adatszerkezetben elfoglalt sorrendjük.
Értelmezhetünk ez alapján főbb műveleteket, melyek szorosan
kötődnek az adott adatszerkezethez. Ismertetjük a
lényegesebbeket:
89
Adatszerkezet
– létrehozás: az adatszerkezet struktúrájának meghatározása,
például megadjuk, hogy egy táblázatban melyik oszlopban mi
fog helyet foglalni
– beszúrás: egy adatelem elhelyezése az adatszerkezetben, a
táblázatban ez egy sor kitöltését jelenti
– törlés: egy adatelem törlése, a táblázatban ez egy sor törlését
jelenti
– megszüntetés: az adatszerkezet struktúrájának a törlése, ez
együtt jár az adatelemek megszüntetésével is
– bejárás: olyan algoritmus alkalmazása, mely során minden
elemet pontosan egyszer érintünk
Ismertek még más műveletek is, de ezek összeállíthatóak a fentiek
segítségével:
– csere: két adatelem cseréje, megoldható egy törléssel és
beszúrással
– rendezés: az adatelemek valamilyen szempont szerinti
sorrendbe állítása, ez is előállítható törlésekkel és
beszúrásokkal
– keresés: egy elem helyének pontos megállapítása, ez a
bejárással mindig elvégezhető
Kétféle osztályozást szoktak említeni az adatszerkezetekkel
kapcsolatban, az egyik az elemek sorrendiségére utal, a másik
pedig az elemek típusaira.
Az első szempont szerint vannak lineáris és nem lineáris
adatszerkezetek. A lineáris adatszerkezet elemei sorozatok, míg a
nem lineáris adatszerkezetre ez nem teljesül.
A másik szempont szerinti osztályozás alapján vannak homogén
és heterogén (inhomogén, nem homogén) adatszerkezetek. A
homogén adatszerkezet elemei azonos típusúak, míg a nem
homogén adatszerkezet elemei különböző típusúak. Ezeknek
kombinációit is tekinthetjük, az alábbi táblázat segítséget nyújt az
eligazodásban.
Homogén Heterogén
Lineáris Egy osztály tanulóinak Egy osztály
90
Adatszerkezetek műveletei
Osztályozásuk
nevei
tanulóinak adatai
Nem lineáris Családfa, mely csak a
neveket tartalmazza
Családfa elemeinek
adatai
91
TartalomBevezetés
1. Lineáris adatszerkezetek
1.1 Tömbök
1.2 Keresések
1.3 A tömb ábrázolása
1.3.1 Hiányos mátrix ábrázolása
Sorfolytonos, oszlopláncolt ábrázolás
Oszlopfolytonos, sorláncolt ábrázolás
Sor és oszlopláncolt ábrázolás.
1.4 Láncolt listák
1.5 Rendezések
1.5.1 Minimum/maximum kiválasztásos rendezés
1.5.2 Buborékos rendezés
1.5.3 Összefuttató rendezés
1.6 Speciális lineáris adatszerkezetek
1.6.1 A verem
1.6.2 Rekurzió
Postfix kifejezés kiértékelése
Infix kifejezés postfixre alakítása
1.6.3 A sor
Dupla végű sorok
Prioritás sorok
2. Nemlineáris adatszerkezetek
2.1 A rekord adatszerkezet
2.1.1 A rekord ábrázolása
2.2 A gráf adatszerkezet
2.2.1 A fa adatszerkezet
2.2.2 A bináris fa
2.2.3 További bináris fák
Összefoglalás
Ellenőrző feladat
Ajánlott irodalom
Gyakorló feladatok megoldásai
92
1. Lineáris adatszerkezetek
1.1 Tömbök
A programozásban a legtöbbször tömböket használunk, minden
programozási nyelv, mely általános célú, támogatja ezek
kezelését. Jellemzője, hogy elemei sorrendje kötött, és az elemek
azonos típusúak. A legegyszerűbb tömb a vektor, mely elemek
sorozata:
34 45 -23 41 867 94 33
Legyen ennek a vektornak a neve SZÁMOK. A vektor elemeit
indexükkel azonosítjuk, mely azt adja meg, hogy a kérdéses elem
hányadik helyet foglalja el a tömb elejéhez képest. A legkisebb
ilyen sorszám az egy, de sok programozási nyelv kezdi nullával is.
Most tekintsük az első elem sorszámát egynek. Ekkor a
következőképpen lehet hivatkozni a tömb első elemére, melynek
értéke 34: SZÁMOK[1], azaz leírjuk a vektor nevét, s mögé
zárójelben az indexet, tehát az elem sorszámát. Ha egy elem
mérete x bájt, s a legnagyobb index, tehát az elemek száma n,
akkor a tömb mérete: x*n.
A másik gyakran használt tömb fajta a mátrix:
Alma Körte Birsalma Cseresznye
Ribizli Szilva Barack Meggy
Szeder Köszméte Málna Eper
Ha a mátrixnak a GYÜMÖLCS nevet adjuk, akkor a Barack elemre
hivatkozhatunk úgyis, hogy leírjuk a tömb nevét, s utána azt, hogy
melyik sorban és oszlopban van: GYÜMÖLCS[2,3]
A tömb egyik fontos jellemzője indexeinek száma, melyet
dimenziónak is szokás nevezni. Ez alapján azt mondhatjuk, hogy a
vektor egy dimenziós, a mátrix pedig két dimenziós tömb. Mivel
93
Tömb jelölése
az indexek számára nincs megkötés, így készíthetünk három
dimenziós tömböt is, ami egy téglatesthez hasonló az iménti
ábrázolási formával, de könnyen lehet kezelni 4, 5, stb. dimenziós
tömböket is. Ha a fantáziánk nagyon élénk, akkor el is tudjuk
képzelni őket, de ne keseredjünk el, ha megragadunk a három
dimenziónál, a számítógép majd elképzeli helyettünk a többit.
A programozásban ezek az adatszerkezetek fontos szerepeket
töltenek be, s fontos ismerni néhány műveletüket. Ha két vektor
azonos elemszámú, akkor lehet venni az összegüket, mely egy
újabb vektor lesz:
A:
23 12 7
B:
4 10 5
C= A+B:
27 22 12
Tehát vektorokat úgy adunk össze, hogy az azonos indexű elemek
összegét vesszük, formálisan:
A[1]=B[1]+C[1]
A[2]=B[2]+C[2]
A[3]=B[3]+C[3]
Vagy általánosan: C[I]=A[I]+B[I]
Egy másik művelet a skaláris szorzat, vagy belső szorzat, jelölése
(A,B), melynek képlete:
A[1]*B[1]+…+A[N]*B[N], ahol N az utolsó elem sorszáma
A fenti két vektorra a példában:
(A,B)=4*23+12*10+7*5=247Mátrixokat is lehet szorozni egymással, de csak abban az esetben,
ha az első n x m típusú, és a második m x k típusú, ez azt jelenti,
hogy az első mátrixban annyi oszlopnak kell lenni, mint amennyi
sor van a másodikban, ugyanis a szorzat eredménye szintén egy
94
Tömb műveletei
A tömb dimenziója
mátrix, mely n x k típusú, tehát n sora és k oszlopa van. A szorzat
mátrix egy általános eleme:
C[i,j]=A[i,1]*B[1,j]+…+A[i,m]*B[m,j]A könnyebb számolás miatt szokás úgy felírni a mátrixokat, hogy a
szemléletesen a megfelelő sor és oszlop metszésében számolható
legyen az eredmény. Szorozzuk össze a következő két mátrixot:
Az „A” mátrix:
2 1
4 2
5 3
A „B” mátrix:
1 3 2
0 2 1
Ekkor a következő alakban írjuk fel őket:
B: 1 3 2
A 0 2 1
2 1 2*1+1*0 2*3+1*2 2*2+1*1
4 2 4*1+2*0 4*3+2*2 4*2+2*1
5 3 5*1+3*0 5*3+3*2 5*2+3*1
Így az eredmény, azaz a C mátrix elemei vannak a vastagon
szedett részben, melyben a számolásokat elvégezve nyerjük a
pontos és egyszerű alakot:
2 8 5
4 16 10
5 21 13
95
Nem csak a vektorokat, hanem a mátrixokat is össze lehet adni,
ha azonos típusúak, és hasonlóan, az összegmátrix elemei a
megfelelő elemek összegei lesznek: C[i,j]=A[i,j]+B[i,j]
1 2 4
+
2 6 7
=
3 8 11
6 5 3 -2 18 4 4 23 7
1.2 Keresések
Tömbökkel szokás megoldani a keresések legtöbbjét, tehát ahol
az elemek azonos típusúak, valamint az átlag és az összegzés
problémáját is.
Maximum keresés algoritmusa:
a. Jelöljük MAXIMUM-mal annak az elemnek az értékét, melynek
minden indexe egyes.
b. Vegyük a tömb bejárása szerinti következő elemet, hasonlítsuk
össze a MAXIMUM-mal, ha a tömb eleme nagyobb, akkor legyen
MAXIMUM értéke vele egyenlő
c. Ismételjük a b. lépést addig, míg a végére nem érünk a tömbnek
Minimum keresés algoritmusa:
a. Jelöljük MINIMUM-mal annak az elemnek az értékét, melynek
minden indexe egyes.
b. Vegyük a tömb bejárása szerinti következő elemet, hasonlítsuk
össze a MINIMUM-mal, ha a tömb eleme kisebb, akkor legyen
MINIMUM értéke vele egyenlő
c. Ismételjük a b. lépést addig, míg a végére nem érünk a tömbnek
Az összeg kiszámítás algoritmusa:
a. Jelöljük ÖSSZEG-gel annak az elemnek az értékét, melynek
minden indexe egyes.
b. Vegyük a tömb bejárása szerinti következő elemet, adjuk hozzá
az értékét az ÖSSZEG-hez, s ez legyen az ÖSSZEG új értéke
96
Keresési algoritmusok
c. Ismételjük a b. lépést addig, míg a végére nem érünk a tömbnek
d. Az ÖSSZEG-ben láthatjuk az elemek összegét
Az átlag kiszámítás algoritmusa:
a. Használjuk az elemek összegének kiszámításához az iménti
algoritmust
b. Jelöljük ÁTLAG-gal azt az értéket, melyet úgy kapunk, hogy
elosztjuk az ÖSSZEG-et az elemek számával
c. Az ÁTLAG-ban láthatjuk az elemek számtani átlagát.
1.3 A tömb ábrázolása
A tömbök ábrázolása egyszerű, az elemeket egymásután helyezik
el a memóriában, olyan sorrendben, ahogy a bejárás műveletében
felsorolják. Kétféle főbb ábrázolási módszer van:
a. Sorfolytonos: Először az első sor elemeit tároljuk egymásután,
majd a másodikét és így tovább
b. Oszlopfolytonos: Először az első oszlop elemeit tároljuk
egymásután, majd a másodikét és így tovább
1.3.1 Hiányos mátrix ábrázolása
Ha az elemek között sok az azonos értékű, akkor csak a tőlük
különbözőeket fogják tárolni. A sok nem egy pontos mérő szám,
97
Gyakorló feladat: Számolja ki a következő két mátrix
összegét
3 3 8 8
1 6 2 4
:
2:. Készítse el a vektor elemeinek átlagát szolgáltató
blokkdiagramot.
Ábrázolási módszerek
ezért a határt mi 80%-nál húzzuk meg, tehát ha több, mint 80%
azonos, akkor úgynevezett hiányos mátrixról beszélünk. Egy ilyen
hiányos mátrix látható a következő ábrán, kivételesen melléírtuk a
sorok és oszlopok sorszámát is, hogy könnyebb legyen később
eligazodni benne:
1 2 3 4 5
1 A A A B A
2 A A A A A
3 A A C A A
4 A A A A D
5 A A A A A
6 A A E F A
7 A A A A G
Láthatjuk, hogy a 35 elemből 29 azonos, csak 6 különböző van
köztük, ilyenkor elég csak ezeket ábrázolni. 3 féle ábrázolás terjedt
el, aszerint, hogy a különböző elemeket milyen sorrendben írjuk
be:
– Sorfolytonos, oszlopláncolt ábrázolás.
A neve mutatja, hogy itt az azonos sorokban lévő különböző
elemeket egymás után írjuk, tehát először az első sor elemeit
tároljuk, majd a másodikét és így tovább. Az eredeti mátrix
visszaállításához szükség van az elemek helyének tárolására is,
ezeket az indexek tárolásával oldjuk meg. A tárolás nevében az
oszlopláncolt azt jelenti, hogy minden tárolt elem esetében
letároljuk azt is, hogy melyik elem jön utána az oszlopában. Ha
nincs elem utána, akkor nullát írunk, vagy valamilyen végjelet,
ellenkező esetben a tároló mátrix azon sorának indexét, ahol az
adott elem elhelyezkedik. Legyen a hiányos mátrixunk az eredeti
példa, megadjuk a tároló mátrixot (itt is feltüntettük a sorok
sorszámát a könnyebb kezelés érdekében, de nem tartozik a
mátrixhoz)
98
Hiányos mátrix ábrázolása
Elem
értéke
Sorának
száma
Oszlopánaks
száma
Oszlopában követke-
ző elem itteni indexe
1 B 1 4 5
2 C 3 3 4
3 D 4 5 6
4 E 6 3 0
5 F 6 4 0
6 G 7 5 0
A sorok kezdetének mutató vektora, az a vektor, mely megadja,
hogy melyik sor hányadik elemmel kezdődik. Ha nincs A-tól
különböző elem, akkor 0-t írunk bele. Ezt a vektort SM-mel
jelölhetjük, a sor mutató rövidítéseként:
SM:
1 0 2 3 0 4 6
Nézzük például a tároló mátrix 3. sorát. Első eleme az D, mivel
sorfolytonosan 3. elemként jelenik meg a bejárásban, ezért került
ide. Következő elem a négyes, mert az eredeti mátrixban a 4.
sorban volt, utána az ötös következik, mert az eredeti mátrixban az
ötödik oszlopban foglal helyet. Az utolsó elem ebben a sorban a 6,
mivel D oszlopában az eredeti mátrixban a G következik, s ennek
a tárolása a tároló mátrix 6. sorában történt. A sormutatót
megtekintve láthatjuk, hogy pl. a 6. eleme a négyes, innen
tudhatjuk, hogy a 6. sor a tároló mátrix negyedik elemével, tehát E-
vel kezdődik. A sormutató és az oszlopláncolásban következő
elem tároló mátrixbeli indexének megadása csupán azt a célt
szolgálja, hogy könnyebben tudjuk kezelni az elemeket a
programozás során.
99
– Oszlopfolytonos, sorláncolt ábrázolás.A neve mutatja, hogy itt az azonos oszlopokban lévő különböző
elemeket egymás után írjuk, tehát először az első oszlop elemeit
tároljuk, majd a másodikét és így tovább. Az eredeti mátrix
visszaállításához szükség van az elemek helyének tárolására is,
ezeket itt is az indexek tárolásával oldjuk meg. A tárolás nevében
a sorláncolt azt jelenti, hogy minden tárolt elem esetében letároljuk
azt is, hogy melyik elem jön utána a sorában. Ha nincs elem
utána, akkor nullát írunk, vagy valamilyen végjelet, ellenkező
esetben a tároló mátrix azon sorának indexét, ahol az adott elem
elhelyezkedik. Legyen a hiányos mátrixunk az eredeti példa,
megadjuk a tároló mátrixot (itt is feltüntettük a sorok sorszámát a
könnyebb kezelés érdekében, de nem tartozik a mátrixhoz)
Elem
értéke
Sorának
száma
Oszlopának
száma
Sorában következő
elem itteni indexe
1 C 3 3 0
2 E 6 3 4
3 B 1 4 0
4 F 6 4 0
5 D 4 5 0
6 G 7 5 0
Az oszlopok kezdetének mutató vektora, az a vektor, mely
megadja, hogy melyik oszlop hányadik elemmel kezdődik. Ha
nincs A-tól különböző elem, akkor 0-t írunk bele. Ezt a vektort OM-
mel jelölhetjük, az oszlopmutató rövidítéseként:
OM:
0 0 1 3 5
Nézzük például a tároló mátrix 2. sorát. Első eleme az E, mivel
sorfolytonosan 2. elemként jelenik meg a bejárásban, ezért került
ide. Következő elem a hatos, mert az eredeti mátrixban a 6.
sorban volt, utána a hármas következik, mert az eredeti mátrixban
100
a harmadik oszlopban foglal helyet. Az utolsó elem ebben a
sorban a 4, mivel E sorában az eredeti mátrixban az F következik,
s ennek a tárolása a tároló mátrix 4. sorában történt. Az
oszlopmutatót megtekintve láthatjuk, hogy pl. a 4. eleme a hármas,
innen tudhatjuk, hogy a 4. oszlop a tároló mátrix harmadik
elemével, tehát B-vel kezdődik. Az oszlopmutató és a
sorláncolásban következő elem tároló mátrixbeli indexének
megadása csupán azt a célt szolgálja, hogy könnyebben tudjuk
kezelni az elemeket a programozás során.
Ezekkel az ábrázolásokkal csak egy gond van, hogy merevek az
eredeti mátrix változásaival szemben, bonyolult lenne újra
generálni a tároló mátrixot. Ezért főként statikus, tehát a nem
változó mátrixok tárolására használják. A következőben
bemutatásra kerül egy olyan ábrázolási mód, mely nagyban
hasonlít az iménti kettőhöz, de kiküszöböli ezt a hiányosságot,
azaz képes dinamikusan változó hiányos mátrixot is tárolni. Ezért
az előnyért fizetni is kell, egy újabb oszloppal fog rendelkezni a
tároló mátrix, és két mutató vektort hozunk létre. A lényeges
különbség az, hogy az elemek sorrendje a tároló mátrixban nem
kötött, véletlenszerűen írjuk bele, akár ki is maradhatnak sorok.
(Az üres sorokat onnan ismerjük meg, hogy csupa nulla van
bennük.) Így viszont meg kell adnunk mind a sorában, mind az
oszlopában utána következő elemet.
101
– Sor és oszlopláncolt ábrázolás.
Elem
értéke
Sorának
száma
Oszlopának
száma
Sorában
következő
elem itteni
indexe
Oszlopában
következő
elem itteni
indexe
1 C 3 3 0 7
2 0 0 0 0 0
3 F 6 4 0 0
4 D 4 5 0 10
5 0 0 0 0 0
6 0 0 0 0 0
7 E 6 3 3 0
8 0 0 0 0 0
9 B 1 4 0 3
10 G 7 5 0 0
A sor és oszlop mutató értelmezése is a szokásos:
OM:
0 0 1 9 4
SM:
9 0 1 4 0 7 10
Látható, hogy az üres sorokba felvihető még elem, s nem kell mást
tenni, csak kitölteni a sort, s esetleg átírni a sor és oszlop mutatót.
Speciálisan szoktuk még ábrázolni a háromszög és szimmetrikus
mátrixokat.
– Háromszög mátrix: A főátló alatti vagy feletti elemek azonosak,
a vagyot kizáró értelemben használjuk. Ilyenkor csak a
különböző elemeket ábrázoljuk
– Szimmetrikus mátrix: Az elemek szimmetrikusak a főátlóra,
azaz A[i,j]=A[j,i]. Ilyenkor is elég csak a felét ábrázolni a
102
Háromszög ésszimmetrikusmátrix
mátrixnak. Csak négyzetes (kvadratikus) mátrixokra
alkalmazható, azaz amelyik mátrixnak ugyanannyi sora és
oszlopa van.
1.4 Láncolt listák
A tömböket statikus adatszerkezetnek kezelik a programozási
nyelvek, tehát méretük a program futása alatt nem változhat, csak
a tartalmuk. Dinamikus lineáris adatszerkezetet a listákkal
hozhatunk létre. Ebben az esetben egy adatszerkezeti elem
tartalmazza magát az adatot és egy memóriacímet, azt, ahol a
következő elem elhelyezkedik. A memóriacím ábrázolása nyilakkal
történik, s arra az adatra mutat, ahova a memória cím hivatkozik.
Lássunk egy egyszerű példát:
A listához tartozik egy listafej, ahol az első elem címét tároljuk,
utána jönnek az elemek. Az utolsó elem mutatója helyén egy X
van, ezzel azonosítjuk a végjelet, tehát ez egy „sehova sem
mutató mutató”, programozási nyelvekben a NIL kulcs szóval
szokás azonosítani. Látható, hogy mindegyik elem eléréséhez
szükség van az előző elem elérésére, a tömbökhöz képest
nehézkes a kezelésük, de nagyon jó olyan szempontból, hogy
tetszőleges számú eleme lehet, méretének csak a memória szab
határt. Az adatelemek típusai tetszőlegesek, de általában azonos
típusúak. A későbbiekben fogunk látni példát inhomogén láncolt
listára is.
103
Láncolt listák
Az üres mutató
Kezelése egyszerű, nagyon könnyű benne beszúrni:
Láthatjuk, hogy csak az első elem mutatóját kell felülírni az új
elemre mutató mutatóval és az új elem mutatóját a régi második
elemre állítani. Az új mutatókat szaggatott vonallal jelöltük. A törlés
talán még egyszerűbb:
Itt csak az első elem mutatóját kell a 3. elemre irányítani, s ezzel
töröltük a második elemet. Az új mutatót szaggatott vonallal
jelöltük itt is.
Ami nehézkes ebben az adatszerkezetben, az a bejárása, ugyanis
az utolsó elem eléréséhez végig kell olvasni az összes elemet.
104
Az utolsó elem mutatóját kicserélve az első elemre mutató
mutatóval, ciklikus listát kapunk:
Ha 2 mutatót rendelünk egy elemhez, akkor lehetőségünk van
arra, hogy visszafelé is tudjunk haladni az elemek között. Ezt
kétirányú láncolt listának nevezik:
Végezetül és elrettentésül nézzünk meg egy bonyolultabb láncolt
listát, mely már nem teljesíti linearitás feltételeit:
105
Ciklikus lista
Kétirányúlista
Nem lineárislista
1.5 Rendezések
A tömbökkel, láncolt listákkal, tehát a lineáris adatszerkezetekkel
szorosan együtt alkalmazhatóak a rendezések, keresések.
Ezekből adunk egy kis ízelítőt:
Rendezésen az adatszerkezet elemeinek valamilyen szempont
szerinti sorba rendezését értjük. A legkézenfekvőbb a nagyság
szerinti sorrend a számok esetében, vagy az ábécé szerinti
sorrend sztringek esetében. A tömbökkel azért tudunk könnyen
rendezni, mert ellentétben a dinamikus listával, elemei elérhetőek
egyből, azaz direkt módon tudunk rájuk hivatkozni.
1.5.1 Minimum/maximum kiválasztásos rendezés
Az elemek egy vektorban vannak elhelyezve, most a minimum
rendezést alkalmazzuk, és növekvő sorrendbe rendezünk. Az
algoritmus a következő:
Válasszuk ki az első elemet, majd a tömböknél ismert módszerrel
határozzuk meg a MINIMUM-ot. Itt annyiban tér el, hogy azt is
meg kell jegyezni, hogy melyik elem volt a minimális. Ha megvan,
106
Gyakorló feladat: Adja meg a következő
hiányos mátrix mind a 3 féle ábrázolását!
1 1 1 1
2 1 4 1
1 1 1 1
1 1 3 1
1 1 6 1
Adja meg a kétirányú ciklikus láncolt lista rajzát!
Kiválasztásos rendezés
cseréljük fel az első elemet a minimális elemre. A következő
lépésben a vektorból elhagyjuk az első elemet, s úgy határozzuk
meg a minimumot, majd kicseréljük a második elemmel. A
harmadik lépésben az első két elemet hagyjuk el, meghatározzuk
a minimumot, s kicseréljük a harmadik elemmel. Általánosan az i.
lépésben elhagyjuk az első i-1 darab elemet, meghatározzuk az
így keletkezett csonka vektorban a minimális elemet, majd
kicseréljük az i. elemmel. Az algoritmus akkor ér véget, ha i=n-1,
ugyanis az utolsó elem már a helyén van, ha az összes őt
megelőző a helyén van.
Ezzel az egy algoritmussal 4 rendezést nyertünk, ugyanis ha nem
az elsővel cserélünk, hanem az utolsóval, akkor csökkenő
sorrendet kapunk, akárcsak akkor, ha nem a minimálist keressük,
hanem a maximális elemet kerestük volna, s azt cseréljük az
elsővel. Ez már a 3. rendezés akkor, a negyediket akkor kapjuk,
ha maximális elemet keresünk, s az utolsóval cseréljük, ilyenkor
növekvő rendezést kapunk.
A rendezés bonyolultsága O(n2)
1.5.2 Buborékos rendezés
Egy gyorsabb rendezési mód, ha a következőt tesszük:
Hasonlítsuk össze az első elemet a másodikkal, ha az első
nagyobb, akkor cseréljünk!
Hasonlítsuk össze a másodikat a harmadikkal, ha a második
nagyobb, akkor cseréljünk. Általánosítva: Hasonlítsuk össze az i.-
et az i+1.-kel, ha az i. nagyobb, akkor cseréljük meg őket!
Végighaladva a vektoron, az utolsó összehasonlítás az n-1. és az
n. elem között lesz. Ha sikerült így végighaladni, biztos, hogy a
legnagyobb elem lesz az n., tehát az utolsó helyen. Megismételve
ezt az iménti lépést újra, már az utolsó kettő lesz a helyén, s ha n-
1-szer megismételtük, minden elem a helyén lesz. Jó
optimalizálási lehetőség, hogy figyeljük azt a tényt, hogy volt-e
csere. Ha nem volt, akár abba is lehet hagyni a rendezést, mert
107
Buborékos rendezés
biztos jó sorrendben van minden elem, valamint az is csökkenti a
lépések számát, ha a már jó helyen lévő elemeket nem hasonlítjuk
össze egymással. A buborék rendezés a nevét onnan kapta, hogy
a legnagyobb elem, mint egy buborék száll fel az őt megillető
helyre.
A rendezés bonyolultsága O(n2)
1.5.3 Összefuttató rendezés
Ha 2 vektorunk van, amelyek rendezettek, akkor nagyon könnyű
belőlük egy harmadik vektort készíteni, mely tartalmazza mindkét
vektor elemeit, és rendezett. Az algoritmus a következő:
Legyen az egyik rendezett vektor A, a másik pedig B, és C-be
szeretnénk rendezni. Tegyük fel, hogy növekvő sorrendben
vannak az adatok (ha nem, akkor fordítsuk meg a helytelen
vektor(oka)t). Hasonlítsuk össze A és B első elemét, a kisebbet
rakjuk bele C-be, majd ha A-ból származott az az elem, akkor
ezentúl A első elemének tekintsük a másodikat, ha B-ből
származott, akkor hasonlóan lépjünk egyet B-ben. Ismételjük meg
az összehasonlításokat mindaddig, míg van elem valamelyik
vektorban, amennyiben csak az egyikben van, folyamatosan írjuk
át a maradék elemeket C-be.
A rendezés hatékonysága O(n).
108
Gyakorló feladat: Hogyan lehet egy számokból álló
állományt rendezni, ha nem fér be a memóriába?
(Ötlet: összefuttatás)
Összefuttató rendezés
1.6 Speciális lineáris adatszerkezetek
1.6.1 A verem
A verem egy olyan speciális vektor, melynek csak az egyik végén
lehet műveletet végezni, tehát beszúrni (PUSH) vagy törölni
(POP). Angol elnevezése Last In First Out, vagy röviden LIFO.
Naponta találkozhatunk ilyennel, például a fagyi tölcsérek is így
helyezkednek el, vagy a szekrényben a törölközők.
Természetesen hivatkozhatunk a rendes hétköznapi veremre is,
de annak szerepét már átvették a hűtőládák, melyek szintén
verem szerkezetűek, hiszen csak a tetejére tudunk betenni
terméket, s onnan tudunk levenni is.
Ábrázolásuk (a nyilak a növekedés irányát jelzik):
A B C D
3
2
1
A vermeket szívesen használják a számítástechnikában,
úgynevezett elhalasztott döntéseknél. Ha az X problémát csak úgy
tudom megoldani, hogy előtte megoldom az Y problémát, akkor
elvermeljük, vagy más szóval elhalasztjuk az X megoldását.
Veremszerkezetűek például a megszakításkezelések a
számítógépnél, tehát egy gyengébb szintű megszakítás kérelem
kiszolgálását elhalasztjuk, ha jön egy erősebb szintű kérelem.
Két probléma vetődik fel a verem kezelésekor:
– Alulcsordulás: Üres veremből akarunk olvasni, ennek kivédése
a programozó feladata
109
LIFO
Elhalasztott döntések
– Túlcsordulás: Teli verembe akarunk beleírni, ennek kivédése a
programnyelv, vagy operációs rendszer feladata, tehát az ő
felelőségük, hogy megfelelő nagy verem álljon rendelkezésre
A túlcsordulás ellen egy jó védekezési módszer, hogy a vermeket
szemben helyezik el egymással, így ha az egyik túlcsordulna,
akkor csak belecsordul a másikba, s ha szerencsénk van, az nincs
teli. Ezt szemlélteti a következő ábra, a nyilak a vermek
növekedési irányát jelzik:
A B C D 3 2 1
Ha az elhalasztott döntéseknél a láncolatban megjelenik az eredeti
probléma, rekurzióról beszélünk. A rekurziónál nagy szerepet kap
a verem, hiszen éppen olyan adatszerkezet, mely képes tárolni
helyes sorrendben a felmerülő problémák összefüggéseit.
1.6.2 Rekurzió
Például a pék akkor tud kenyeret készíteni, ha a molnár őröl
lisztet, de ő csak akkor tud őrölni, ha gátőr kinyitja a zsilipet, de ő
csak akkor tudja kinyitni, ha nem kell vigyázni a gyerekére, de
csak akkor nem kell vigyázni, ha otthon van a felesége, de ő csak
akkor van otthon, ha tud venni kenyeret (vagy zsemlét), de csak
akkor tud venni kenyeret, ha süt a pék. Tegyük fel, hogy zsemle
mindig van, mert különben megállna ebben a világban az élet.
A rekurzió nem csak ilyen népmeseszerűen jelenik meg, hanem a
matematikában is. Nem kell bonyolult dologra gondolni, ilyen
például a faktoriális definíciója:
N!=(N-1)!*NLáthatjuk, hogy a faktoriális kiszámításához szükségünk van a
faktoriálisra. Ez elég kellemetlen, ugyanúgy patt helyzetbe
kerülünk, mint a pék, ha nincs zsemle mégsem. Szerencsére van
megoldás, ugyanis ha biztosítunk egy egérutat, akkor feloldódik ez
a helyzet:
110
Védekezés a túlcsordulás ellen
A faktoriális rekurzív képlete
N!=0. Tehát ha számolom 3! értékét, akkor tudnom kell a 2!, ahhoz
tudnom kell az 1!, ahhoz tudnom kell a 0!, de azt tudom! Ezek
szerint tudni fogom 1! értékét is, de akkor tudni fogom 2! értékét és
így 3! értékét is.
A fentiek alapján azt mondjuk, hogy jóldefiniált egy rekurzió, ha van bázis kritérium, melynek teljesülése esetén nem rekurzív a megoldás, és minden rekurzív lépéssel egyre közelebb kerülünk ennek a báziskritériumnak a teljesítéséhez, és végül el is érjük azt.
A faktoriálisnál ez a báziskritérium a 0! volt, a pékes példában
pedig az, hogy az asszony esetleg hajlandó kivételesen zsemlét
venni.
Nézzünk még néhány rekurzív problémát (dőlttel szedtük a bázis
kritériumot):
– ai=ai-1 * a, és a0=1, hatványozás (i természetes szám)
– ai=ai-1+ai-2, és a1=0, a2=1, Fibonacci számok (0,1,1,2,3,5,..)
– lnko(a,b)= lnko(a-b,b), ha a>b; lnko(a,b)= lnko(a,b-a), ha b>a;
és lnko(a,a)=a
– Hanoi tornyai: Adott 3 rúd, melyek közül az elsőn korongok
vannak felfűzve. Helyezzük át a harmadik rúdra ezt a halmot,
de úgy, hogy egyszerre csak egy korongot rakhatunk át,
valamint vagy üres rúdra tesszük, vagy pedig tőle nagyobb
korongra. Ezt a problémát Hanoi tornyainak nevezik. A
megoldás az, hogy ha van 10 korongom, át tudnám pakolni, ha
valaki megmutatja, hogy 9-et hogy kell, mert akkor 9-et
áttetetek a középsőre, a legalsót átteszem a harmadikra, s
rápakoltatom a 9-et a középsőről erre azzal a valakivel. Kilenc
esetében mással pakoltatnánk a nyolcat, és így tovább, a
végén egyet kellene valakivel pakoltatni, de azt pedig gond
nélkül megtehetjük, így megoldható a probléma. A probléma
megoldása azért nem gyors, Hanoi felé az a mondás járja,
hogy ha átpakolják a korongokat, vége a világnak.
111
Jóldefiniált rekurzió
Adja meg a
probléma
lépésszámát
1000 korong
esetén, s tegyük
fel, hogy egy
pakolás 1
másodpercig
tart. Mennyi idő
alatt oldható meg
a feladat?
A bázis kritérium
Egy labirintusból is ki tudunk jönni, ha az előttünk lévő ki tud
menni, de ő pedig akkor tud, ha az ő előtte lévő, és így tovább. Ha
mindenki körül van ember, akkor biztos van valaki a kijáratnál is,
így sikeresen szabadulhatunk. Azért ettől biztosabb módszer, ha
megfogjuk egyik kezünkkel a falat, s úgy indulunk el, így is biztos
kijutunk.
A vermek másik érdekes felhasználási területe a kifejezések
kiértékelése. Itt most kifejezések alatt valamilyen matematikai
műveletsort értünk, pl. az 5+4*(1+3) kifejezést. A gondot az jelenti,
hogy a zárójelezést figyelni kell, hiszen
5+4*(1+3)=21, míg 5+4*1+3=12. Ez azt jelenti, hogy ki kell keresni
a legbelső zárójelet, annak értékét meghatározni, stb. Láthatjuk,
hogy nem egyszerű feladat. Szerencsére a kifejezéseknek van
más alakjuk is, melyekben nem kell zárójeleket használni. Nézzük
meg a kifejezések lehetséges alakjait:
3+4–––infix forma, a műveleti jel a tagok között+34–––prefix forma (lengyel forma), a műveleti jel a tagok előtt34+–––postfix forma (fordított lengyel forma) a műveleti jel a
tagok mögött helyezkedik el.
Postfix kifejezés kiértékelése
A kifejezések postfix alakjában nem szükséges zárójelet
alkalmazni, ezért ilyenre szokták átfordítani az infix kifejezéseket.
Először nézzük meg, hogyan tudunk kiértékelni egy postfix
kifejezést, mennyi lesz 5413+*+ értéke? A kiértékelés szabályai:
– ha operandust olvasunk, az a verembe kerül,
– ha operátort, akkor kivesszük a veremből az elvégzéséhez
szükséges operandusokat, majd az eredményt a verembe
tesszük,
– A postfix kifejezés végigolvasása után a veremben lesz az
eredmény.
Alkalmazzuk ezt az algoritmust a példánkra, előre írjuk az olvasott
jelet, mellé a verem tartalmat az olvasás után:
112
5 5
4 4 5
1 1 4 5
3 3 1 4 5
+ 4 4 5
* 16 5
+ 21
Láthatjuk, hogy valóban ugyanazokkal a számokkal és műveleti
jelekkel sikerült leírni az infix kifejezésnek megfelelő postfix
kifejezést zárójelek nélkül.
Infix kifejezés postfixre alakítása
Megadjuk általánosan is az infix kifejezést postfixre alakító
algoritmust. Jelöljük az infix kifejezést Q-val, az elkészítendő