BETŰK RENDEZÉSÉTŐL EGY VALÓS SZÁMOKAT TARTALMAZÓ VEKTOR RENDEZÉSÉIG FROM ALPHABETICAL ORDERING TO SORTING REAL NUMBERS Kiss László Óbudai Egyetem, Rejtő Sándor Könnyűipari és Környezetmérnöki Kar, Médiatechnológai és Könnyűipari Intézet
KIVONAT Cikkemben szeretném végigvezetni a hallgatóságot azon a gondolkodási folyamaton, hogy hogyan juthatunk el egy általában ismert algoritmustól, mint az angol ABC nagybetűit tartalmazó szöveg karaktereinek ABC sorba rendezése, egy egész számokat tartalmazó vektor rendezésén át, egy valós számokat tartalmazó vektor rendezésének érdekes megvalósításáig. A kitűzött cél: az elemszám növekedése esetén – bizonyos esetekben – elérni, hogy az idő lényegében lineárisan változzon. Előnye a megvalósításnak, hogy ugyanezen az elven a számhalmaz mediánját is hatékonyan meghatározhatjuk. A fentiek szemléltetésére Excelben VBA alkalmazásokat is bemutatok. Módszertani szempontból fontosnak tartom, hogyan térhetünk el a szokásos gondolatmenettől egy feladat megoldása során, és juthatunk el általa egy talán jobb, vagy később jobbá tehető, de mindenképpen más módszerhez. ABSTRACT This presentation is a step-by-step demonstration of the thought process that starts from a generally known algorithm, such as ordering letters of the English alphabet, and extends it first to sorting a dense vector containing integers, then to an interesting implementation of sorting a vector of real numbers. The aim is to arrive at an algorithm that is in certain cases capable of meeting a practically linear time requirement. An additional advantage of the same implementation principle is that it allows finding the median of the set efficiently. Excel VBA applications are used as a demonstration. From a methodological point of view this is an example where thinking outside the box leads to an unconventional solution that has the potential to surpass the usual solution. KULCSSZAVAK/KEYWORDS Algoritmusok, programozás, oktatásmódszertan Algorithms, programming, teaching methodology MOTTÓ Minden mindennel összefügg, minden algoritmus, és minden függvény.
You created this PDF from an application that is not licensed to print to novaPDF printer (http://www.novapdf.com)
BEVEZETÉS Az élet különböző helyzeteiben különböző algoritmusok, folyamatok részesei vagyunk. Sokszor egyáltalán nem ismert a következő lépés vagy állapot, annyi mindentől függ. Nagyon fontos, hogy tekintetünket az egészre próbáljuk emelni, hogy lássuk az összefüggéseket, a végbemenő folyamatokat és a feltételeket, amelyek azokat befolyásolják. Ebben a szemléletben gondolkodva sokszor lényeges, hogy el tudjunk szakadni attól a gondolkodási sémától, amit egy adott állapot sugall számunkra. A különböző tudományokban is alkalmazhatjuk ezt a módszert egy-egy probléma megoldása során. Emiatt fontosnak tartom, hogy ismertessük meg ezt a gondolkodásmódot az oktatás különböző területein és szintjein a hallgatókkal, hogy mind az életben, mind munkájukban alkalmazhassák. A témát előszeretettel vezetem be azokkal a logikai feladatokkal, amelyeket a Rátz László Vándorgyűlésen, 1997-ben, a gondolkodásról tartott előadásomhoz állítottam össze, melynek megtartásában nagy szerepet játszott [1] és [2] tanulmányozása. LOGIKAI FELADATOK 1) Adott négyzetrács alakban 9 pont. Kössük össze őket 4 egyenes vonallal a ceruza felemelése nélkül. 2) Négy hajóról tudjuk, hogy egymástól egyenlő távolságra vannak. Az egyik vitorlás, a másik halászhajó, a harmadik utasszállító. Milyen a negyedik? 3) Egy nagy átmérőjű, egyenes, rövid csőbe, aminek mindkét vége nyitott, a két végén belenézett két macska, és nem látták egymást. Hogyan történhetett ez? 4) Egy cowboy Pénteken belovagolt a városba, hogy a marháit eladja. Még aznap sikeresen eladta mindet. Bement a kocsmába és két nap két éjjel ivott, majd azonnal hazatért. Mégis Pénteken ment haza. Hogyan volt ez lehetséges? 5) a) A sivatagban, déli 12 órakor egy légionáriust elkapnak a beduinok. Halállal kell lakolnia, ha egy sapkából a 10 fekete és 1 fehér kő közül csukott szemmel nem tudja kivenni a fehéret. Ő a feladatot mosolyogva oldja meg. Hogyan csinálta? b) Adott két szoba. Az egyikben 3 kapcsoló lekapcsolt állapotban, a másikban – hozzájuk tartozóan – 3 villanykörte. Először a "kapcsolós" szobába mehetünk be, ahol bármelyiket kapcsolgathatjuk, majd a "körtés" szobába, de onnan a "kapcsolós"-ba már nem térhetünk vissza. Meg tudjuk e mondani, hogy melyik kapcsolóhoz melyik körte tartozik? A megoldások során rendre a négyzet, a sík, a tér, az idő, és végül a matematika területét hagyjuk el, és gondolkodunk más nézőpontból. BETŰK (KARAKTERSOROZAT) RENDEZÉSE Az angol ABC nagybetűiből álló szövegben a karaktereket ABC sorba szeretnénk rendezni. Megoldhatjuk a feladatot valamelyik vektorrendezés elvén. A szöveg hosszát ismerve, a karaktereket egyenként leválasztjuk, és egy vektorban helyezzük el. A vektor elemeit növekvőbe rendezzük, majd szöveggé összefűzzük. Az ettől eltérő megoldás alapja, hogy ismerjük a nagybetűk ASCII kódjait (A=65, B=66, …, Z=90). Felveszünk egy 26 elemű vektort (jelölje: V), amiben minden elem kezdeti értéke nulla. Leválasztjuk sorban a karaktereket (jelölje az éppen leválasztott karaktert: C).
You created this PDF from an application that is not licensed to print to novaPDF printer (http://www.novapdf.com)
Alkalmazzuk a következő leképezést: K=Asc(C)-64 (itt ASC az a függvény, ami egy karakterhez annak ASCII kódját rendeli). Ekkor K értéke 1 és 26 közé esik. Legyen V(K)=V(K)+1. Ha minden karaktert feldolgoztunk, akkor V(K) az angol ABC K-adik betűjének szövegbeli előfordulási számát mutatja. Ezután felveszünk egy üres szöveg típusú változót (S), majd a V vektor elemein végighaladva a K-adik betűt (C=Chr(K+64)) V(K)-szor ciklusban S-hez fűzzük, és megkapjuk a keresett, rendezett karakterekből álló szöveget. Az 1. ábrán az oszlopindexek éppen az angol ABC nagybetűi. Az 1. sor értékei az egyes betűk sorszáma, ami éppen az algoritmus lehetséges K értékeivel egyezik meg. A 3. sor a rendezésre váró, a 4. a rendezett karaktereket tartalmazza. A 2. sor a V vektort szemlélteti, vagyis azt láthatjuk, hogy a rendezni kívánt karaktersorozatban (szövegben) az egyes karakterek hányszor fordultak elő. Természetesen ezt az algoritmust ki lehet terjeszteni teljes szövegekre (amelyek nagybetűt, kisbetűt és egyéb karaktereket is tartalmaznak), de most nem ennek a tárgyalása a cél. EGÉSZ SZÁMOKAT TARTALMAZÓ VEKTOR RENDEZÉSE Előbbi ötletünket alkalmazhatjuk olyan egész számok rendezésére is, ahol a legnagyobb és legkisebb szám különbsége nem túl nagy. Meghatározzuk a számok minimumát (MIN) és maximumát (MAX), felveszünk egy V vektort, aminek MAX-(MIN-1) eleme van, és minden elem értéke kezdetben nulla. A rendezni kívánt számok mindegyikéhez (jelölje az éppen vizsgáltat: J) hozzárendeljük a K=J(MIN-1) indexet, majd a V vektor K-adik elemét 1-el megnöveljük (V(K)=V(K)+1). Ezzel a módszerrel az elemeket osztályokba soroltuk. Egy osztály létszámát V vektor megfelelő eleme adja, és az egy osztályba tartozó számok megegyeznek. Ezután sorban feldolgozzuk V összes elemét. Az éppen aktuális elem indexéhez (jelölje: K) hozzáadjuk az MIN-1 számot (J=K+(MIN-1)), és az így kapott értéket V(K)-szor vesszük. Ezzel az egész számokból álló halmazt rendezetten kapjuk vissza. A két algoritmus ugyanazon az elven alapszik: megszámoljuk az egyes előfordulásokat. Számlálás közben az indexekből mindkét esetben tulajdonképpen (a lehetséges minimumérték-1)-et vonunk ki, azért, hogy a számláló vektor a lehető legkisebb elemszámú legyen. A rendezésnek ezt az alapötletét, Knuth szerint, Harold H. Seward találta ki 1954-ben [3]. EGYENLETES ELOSZLÁSÚ VALÓS SZÁMOK RENDEZÉSE Valós számokat nem tudunk úgy megszámolni, mint azt az egészekkel tettük, de fenti ötletet alkalmazhatjuk arra, hogy rendezettségüket tekintve előbbre jussunk. Keressük meg a számok maximumát (MAX) és minimumát (MIN). Tekintsük a MAXMIN értéket. Ez a számok legnagyobb távolsága. Jelölje X a számok egyikét. Vegyük az DX=(X-MIN)/(MAX-MIN) értéket. Mivel MIN<=X<=MAX, ezért 0<=DX<=1. Legyen K a DX*(M-1) egészrésze plusz 1 (K=1+Int(DX*(M-1))). Akkor K egész szám, és 1<=K<=M. Tehát a K=1+(Int((X-MIN)*(MAX-MIN)*(M-1)) függvény a valós számok egy tetszőleges halmazát leképezi az 1, 2, …, M egész számok halmazára. Ezzel a valós számokat M osztályba soroltuk. A leképezésre nyilvánvalóan igaz, hogy ha két szám képe nem azonos, akkor közülük az a nagyobb, amelyikhez nagyobb egészet rendeltünk. Ha azt is tudjuk, hogy a valós számok a számegyenesen egyenletesen találhatók, akkor az egyes osztályok elemszáma (létszáma) közel azonos. Algoritmusunk a fentieken alapul.
You created this PDF from an application that is not licensed to print to novaPDF printer (http://www.novapdf.com)
Megvizsgáljuk a számokat (K=1+(Int((X-MIN)*(MAX-MIN)*(M-1))), és közben számoljuk egy vektorban (V(K)=V(K)+1), hogy egy-egy osztály milyen számosságú. Ezután egy másik vektorban meghatározzuk az egyes osztályok kezdőindexeit. Az első osztály kezdőindexe 1 (KC(1)=1). Minden következőé az előző kezdőindexe + az előző számossága (KC(I)=KC(I-1)+V(I-1), 2<=I<=M). Ezután újra olvasva számainkat, és újra kiszámolva, hogy melyik osztályba tartoznak, elhelyezzük őket egy új vektorban a kezdőindexeket mutató vektornak az adott osztályra vonatkozó értéke, mint index alapján, amelyet minden elhelyezett szám után megnövelünk 1-gyel. Az eljárás végén a kezdőindex-vektor elemei éppen az 1-el nagyobb indexű osztály kezdőindexét tartalmazzák. Ezzel a módszerrel számaink az új vektorban részben rendezettek, hiszen a nagyobb indexű osztályban lévők nagyobbak, mint a kisebb indexű osztálybeliek. A feladat már csupán az, hogy az egyes osztályban található számokat valamilyen rendezési algoritmussal rendezzük. Figyelnünk kell az osztályok kezdőindexeit tartalmazó vektor tartalmára. A számok mennyiségétől és a tárolási lehetőségeinktől függően szabhatjuk meg az osztályok számát, ami egyben az osztályban átlagosan található elemszámot is meghatározza. A rendezésnek ez az algoritmusa felfogható az edényrendezés (alapötlete: E. J. Isaac és R. C. Singleton, 1956 [3]) kiterjesztéseként is a valós számok tetszőleges intervallumára, de attól teljesen mértékben eltér az osztályok (edények) létrehozásában és feldolgozásában. A módszert, Vonnák Ivánnal közös ötletünk alapján, valamikor 1979 és 1982 között programoztam be először, és alkalmaztam a következő fejezetben leírt mediánkeresésre is. Bár erre a megvalósításra utaló cikket vagy könyvet nem találtam, egyáltalán nem zárom ki, hogy az ötlet nem egyedül bennünk született meg. Készítettem egy alkalmazást, ami egész szám tesztadatokra különböző elemszám esetén végrehajtja a buborékrendezést, a számláló (leszámláló) rendezést Excel cellák illetve részben belső vektorok használatával, és az ismertetett osztályozó rendezést Excel cellák illetve részben belső vektorok használatával. Utóbbinál az átlagos osztálylétszám 3, azaz az osztályok száma az egész számok számának harmada (M=Int(N/3). A teszteredményeket átlagoltam, majd a rendezési időket elosztottam az elemszámmal, és grafikonon ábrázoltam. A buborékrendezés (1. ábra) és a számláló rendezés (2. ábra) grafikonja megfelel a szakirodalomban olvasottaknak. Az osztályozó rendezés grafikonjáról (3. ábra) leolvasható, hogy az 1 számra (vektorelemre) vonatkozó rendezési idő az elemszám függvényében – hasonlóan a számláló rendezéshez - nem növekszik. Lényegében állandó. Egy másik alkalmazással azt teszteltem, hogy az osztályok száma hogyan hat az 1 vektorelemre eső rendezési idő értékére. Azt tapasztaltam, hogy minél kisebb egy osztály létszáma, annál kisebb a rendezés egy elemre eső ideje is (4. ábra). Ha tehát van elég tárterületünk, akkor pontosan annyi osztályba érdemes a valós számokat sorolni, ahányan vannak. MEDIÁN KERESÉSE EGYENLETES ELOSZLÁSÚ VALÓS SZÁMHALMAZON. A valós számok rendezésénél alkalmazott osztályba sorolást felhasználhatjuk a számok mediánjának meghatározására. Ha számuk páratlan, akkor – az egyes osztályok számosságának ismeretében – pontosan tudjuk, hogy a középső melyik osztályban található, és abban hányadik. Ha páros, akkor a két középső közül a nagyobbról ugyanezt ismerjük. Ha az nem egy osztály legelső eleme, akkor mindketten ugyanabban az osztályban vannak, és azt is tudjuk, hogy
You created this PDF from an application that is not licensed to print to novaPDF printer (http://www.novapdf.com)
hányadik elemek. Ha az egy osztály első eleme, akkor annak minimuma, és a kisebbik a megelőző osztály maximuma. Így az algoritmus az alábbi: Legyen a valós számok száma N. Páratlan esetben a középső, páros esetben a két középső közül a nagyobb rendezettségben kapott indexe J=1+Int(N/2). Fentiek szerint meghatározzuk az osztályok létszámát, azaz kitöltjük a számláló vektort. A számláló vektor elemeit 1-hez hozzáadva összegezzük mindaddig, amíg az összeg értéke nagyobb vagy egyenlő nem lesz, mint J. (Tulajdonképpen kiszámítjuk az egyes osztályok kezdőcímeit (kezdőindexeit), csak azokat nem tároljuk most vektorban.) Ha egyenlő, akkor páratlan elemszám esetén a medián az adott osztály minimuma. Páros elemszámnál szükségünk van a megelőző osztály maximumára is. Ezután újra megvizsgálva a számokat, egyúttal meghatározzuk az adott osztály minimumát, illetve páros esetben a megelőző maximumát, majd a két szám átlagát, és ezzel a mediánt. Ha nagyobb, akkor a medián, illetve páros esetben a mediánhoz szükséges két érték mindegyike a megelőző indexű osztályban van. (Nyilvánvaló, hogy a megelőző osztály ebben az esetben nem lehet 1 létszámú.) Az osztály számosságát ismerve azt is tudjuk, hogy annak melyik felében, azaz a rendezettségben „alulról” vagy „felülről” hányadik elemet, vagy elemeket kell meghatároznunk. Ennek megfelelően újra megvizsgáljuk a számokat, az adott osztály elemeit elhelyezzük egy vektorban (elemszáma az osztálylétszám), majd a vektorra a buborékrendezésnél megismert cserélgetési eljárást, növekvőben vagy csökkenőben, szükséges számban alkalmazzuk, és páros esetben átlagot számolunk. Készítettem egy alkalmazást, amelyik generált tesztadatokból fenti algoritmussal, az Excel medián függvényével, illetve belső rendezőjével - rendezve a tesztadatokat - számítja ki a mediánt. A tesztelések során azt tapasztaltam, hogy az algoritmus a rendezéses megoldásnál egyértelműen gyorsabb, a medián függvény alkalmazásával pedig lényegében azonos időigényű (hol több, hol kevesebb, de közel azonos). Figyelembe véve, hogy az algoritmus VBA-ban, tehát interpreterben megírt, ami a futás közben még a programszöveget is kell, hogy értelmezze, szemben utóbbiakkal, valószínűsíthető, hogy azonos nyelven megírva egyértelműen gyorsabb (2. táblázat). ÖSSZEFOGLALÁS/KÖVETKEZTETÉS Végigjártunk egy gondolkodási utat, hogyan térhetünk el az adott gondolkodási sémától a betűk, egész számok és valós számok rendezése során. Hogyan alkalmazhatjuk módszerünket a medián meghatározására. Az elért eredményekkel elégedettek lehetünk, hiszen a valós számokra alkalmazott rendezési algoritmus időgrafikonja lineáris, és a medián meghatározása a VBA kód ellenére nagyon gyors. Bízom benne, hogy az olvasó érdekesnek találta a gondolkodásnak ezt a megközelítését, és az ismertetett algoritmusok hozzásegítik ahhoz, hogy keresse az új utakat. IRODALOMJEGYZÉK [1] Hatvany László: KARÁCSONY SÁNDOR PEDAGÓGIAI ÍRÁSAIBÓL (9 tanulmány, 1922-1946), Csökmei Kör, 1994 [2] Karácsony Sándor: A tanulás mesterfogásai, Csökmei Kör, Pécel, 1998 ISBN: 963 03 55205 [3] Cormen, Leiserson, Rivest: Algoritmusok, Műszaki Könyvkiadó, 2003, ISBN: 9789631630299
You created this PDF from an application that is not licensed to print to novaPDF printer (http://www.novapdf.com)
SZERZŐ Kiss László, főiskolai docens, ÓE RKK MKI,
[email protected]
You created this PDF from an application that is not licensed to print to novaPDF printer (http://www.novapdf.com)
1. táblázat. Az angol ABC nagybetűiből álló karaktersorozat rendezése.
2. táblázat. A rendezéseket összehasonlító alkalmazás az „Osztályozó rendezés Excel cellákkal” futása után, a „Buborékrendezés” futása előtt.
Adatok megnevezése
Generált és később Osztály Számok Kezdő Aktuális rendezett létszáma rendezetten címek címek számok
Adatok
Véletlen számok száma: Véletlen számok maximális értéke: Véletlen számok oszlopindexe: Kezdő sorindex az oszlopban
17 20 4 2
Minimum Maximum
1 20
Leszámláló rendezés belső vektorral Leszámláló rendezés cellákkal Osztályozó rendezés belső vektorral Osztályozó rendezés cellákkal Buborékrendezés Megállít (0 =nem, 1=igen)
0,015625 0,046875 0,031250 0,062500
0
5 8 19 12 8 20 6 7 1 10 12 5 6 18 20 11 3
4 6 3 2 2
1 3 5 5 6 6 7 8 8 10 11 12 12 18 19 20 20
1 5 11 14 16
5 11 14 16 18
3. táblázat. Valós számok mediánjának meghatározása, összehasonlítással.
You created this PDF from an application that is not licensed to print to novaPDF printer (http://www.novapdf.com)
1. ábra. Buborékrendezés relatív idődiagramja az elemszám függvényében
2. ábra. Számláló rendezés relatív idődiagramja az elemszám függvényében
You created this PDF from an application that is not licensed to print to novaPDF printer (http://www.novapdf.com)
3. ábra. Osztályozó rendezés relatív idődiagramja az elemszám függvényében
4. ábra. Osztályozó rendezés relatív idődiagramja az elemszám és az osztályok számának függvényében (osztályok száma = elemszám/jelmagyarázat érték egészrésze)
You created this PDF from an application that is not licensed to print to novaPDF printer (http://www.novapdf.com)