[[oktatas:programozás:algoritmusok|< Algoritmusok]] ====== Apróbb algoritmusok ====== * **Szerző:** Sallai András * Copyright (c) 2013, Sallai András * Szerkesztve: 2013, 2014, 2015 * Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC BY-SA 4.0]] * Web: https://szit.hu ===== Bevezetés ===== Itt olyan algoritmusok vannak, amelyeket nem szoktunk a programozási tételek között felsorolni, mert vagy nagyon ritkán használjuk vagy nagyon triviális, vagy nagyon összetett, esetleg speciális. ===== Faktoriális számítása ===== Egy n nemnegatív egész szám faktoriálisának az n-nél kisebb vagy egyenlő pozitív egész számok szorzatát nevezzük. Jelölése: n! Néhány szám kibontva: 0! = 1 1! = 1 2! = 1 * 2 = 2 3! = 1 * 2 * 3 = 6 4! = 1 * 2 * 3 * 4 = 24 5! = 1 * 2 * 3 * 4 * 5 = 120 A sorozat eleje: ^ 0! ^ 1! ^ 2! ^ 3! ^ 4! ^ 5! ^ 6! ^ 7! ^ 8! ^ 9! ^ 10! ^ 11! ^ 12! ^ | 1 | 1 | 2 | 6 | 24 | 120 | 720 | 5040 | 40320 | 362880 | 3628800 | 39916800 | 479001600 | Algoritmus: fakt = 1 ciklus i = 2 .. n fakt = fakt * i Rekurzívan: függvény fak(szam){ ha szam == 0 akkor visszatér 1 else visszatér fak(szam-1)*szam } public class Program01 { public static long fakt(int szam) { if (szam == 0) { return 1; }else { return fakt(szam-1)*szam; } } public static void main (String[] args) { for(int i=1; i<10; i++) { System.out.println(fakt(i)); } } } ===== Fibonacci számok ===== Fibonacci egy itáliai matematikus volt. Több néven ismert: Leonardo di Pisa, Leonardo Pisano, Leonardo Bonacci, Leonardo Fibonacci. Születése és halála pontosan nem ismert: (kb. 1170 – kb. 1250). Az arab számokat ő terjesztette el.A róla elnevezett számsorozatot nem ő találta ki, de az ő írásai után lett híres. Az adott elem mindig az előtte lévő két elem összege. A Fibonacci-sorozat 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987 függvény fib(szám) { ha ( szam <= 1 ) { visszatér szám; } ellenben { visszatér fib(szám-1) + fib(szám-2); } } ciklus i= 1..30 fib(i) ciklus vége public class Program26 { public static int fib(int szam) { if(szam <= 1) { return szam; }else { return fib(szam -1) + fib(szam-2); } } public static void main (String[] args) { for(int i=1;i<23;i++) { System.out.println(fib(i)); } } } ===== Csere ===== Csere esetén egyszerűen fel kell venni egy segédváltozót, amiben eltároljuk az egyik cserélendő értéket. Legyen például egy "a" és egy "b" nevű változó, amelyben számokat tárolunk és ezen változók tartalmát szeretnénk cserélni: c = a a = b b = c A segédváltozó a "c" lett (szokásos elnevezés például a "swap"). Először elteszem "a" értékét. Ezek után felülírhatom az "a" változót. A végén "b" változó értéke "c"-ben lesz. ===== Végrehajtás végjelig ===== Valamilyen külső körülménytől várjuk a végjelet. Ez lehet egy felhasználói beavatkozás, de lehet adatbázisból állományból vett adat. be adat ismétel amíg adat <> végjel az adat feldolgozása be adat ismétlés vége ===== Átlag ===== Az átlag az elemek összegének és az elemek darabszámának hányadosa. ==== JavaScript megvalósítás ==== function selectAverage(inArray){ var n = inArray.length; var sum = 0; for(i=0;i ===== Lottószámok ===== Klasszikus probléma a lottó számok generálása. 1 és 90 között véletlenszerűen választanunk kell egy számot. Ez után megint 1 és 90 között kell véletlenszerűen választani egy számot, de az nem egyezhet meg a már kiválasztottal. Az első gondolat az lehet, hogy generáljunk egy véletlen számot, tegyük egy listába, majd a következő szám generálásánál nézzük meg, hogy az új szám szerepel-e már a listában. Ha igen, kérjünk újat. Kicsi az esélye, hogy sokáig kell futnia az algoritmusnak, de elegánsabb a következő algoritmus. Készítsünk egy listát amelyben az összes kihúzható szám szerepel 1-90-ig. Generáljunk egy véletlen számot például 1 és 90 között. A szám az első szám indexe a listában. Első körben az index és a listában szereplő szám egyezik. Ez után vegyük ki listából az előbb kiválasztott számot, jegyezzük fel lottószámként. Kezdjük újra a véletlen szám generálást, de most már egyel kevesebb számsorból. Ismételjük a fentieket, ötször. ===== Módusz ===== A módusz a leggyakrabban előforduló elem. Legyen a következő sorozat: | 3 | 2 | 8 | 3 | 2 | 1 | 4 | 2 | 2 | 1 | A leggyakrabban előforduló elem a 2. ==== Mondatszerűen ==== start maxValue=0 maxCount=0 ciklus i = 0 .. a.Hossz count = 0; ciklus j = 0 .. a.Hossz ha a[j] == a[i] akkor count = count + 1 ha count>maxCount akkor maxCount = count maxValue = a[i]; ha vége ciklus vége vége A végén a maxValue változó tartalmazza a leggyakrabban előforduló elemet. ==== JavaScript megvalósítás ==== function modusz(atvettTomb){ var maxValue=0; var maxCount=0; var n = atvettTomb.length; for(i=0; imaxCount){ maxCount = count; maxValue = atvettTomb[i]; } } return maxValue; } ==== Java megvalósítás ==== Java megvalósítás egészeket tároló ArrayList osztállyal: public static Integer selectModusz(java.util.ArrayList inList){ Integer maxValue =0; Integer maxCount = 0; Integer n = inList.size(); for(int i=0; imaxCount){ maxCount = count; maxValue = inList.get(i); } } return maxValue; } ===== Medián ===== A medián a helyzeti középérték. Páratlan elem szám esetén a középső elem a medián. Páros elem szám esetén a két középső elem átlaga. A számoknak **rendezettnek kell lenniük**. ^ Index: | 0 | 1 | 2 | 3 | 4 | ^ Sorozat: | 2 | 3 | 7 | 8 | 9 | ^ Index: | 0 | 1 | 2 | 3 | 4 | 5 | ^ Sorozat: | 2 | 3 | 7 | 8 | 9 | 10 | ==== Mondatszerűen ==== start kozep = m.Hossz/2; ha (m.Hossz % 2 == 1) median = m[kozep]; ellenben median = (m[kozep-1] + m[kozep]) / 2.0; ha vége vége ==== JavaScript megvalósítás ==== function median(atvettTomb){ var kozep = atvettTomb.length / 2; var median = 0; if(atvettTomb.length % 2 == 1) median = atvettTomb[kozep]; else median = (atvettTomb[kozep-1] + atvettTomb[kozep]) / 2.0; return median; } ==== Java megvalósítás ==== public static Double selectMedian(java.util.ArrayList inList){ Integer mid = inList.size() / 2; Double median = .0; if(inList.size() % 2 == 1) median = (double) inList.get(mid); else median = (inList.get(mid-1) + inList.get(mid))/2.0; return median; } Rendező metódus ha kell: public static ArrayList sortIntegerList(ArrayList inList){ int n = inList.size(); for(int i= n-1; i>0; i--) for(int j=0; j inList.get(j+1)) { Integer tmp = inList.get(j); inList.set(j, inList.get(j+1)); inList.set(j+1, tmp); } return inList; } ===== Legnagyobb közös osztó ===== * egész euklidesz(a, b) * ha b == 0 akkor * return a * ellenben return euklidesz(b, a mod b) #include /* Legnagyobb közös osztó az euklidészi algoritmussal Bemenő paraméterek nem nagatív egész számok */ int lnko(int a, int b) { if(b==0) { return a; }else { return lnko(b, a % b); } } int main(int argc, char **argv) { printf("%d\n", lnko(35, 42)); return 0; } ===== Prímtényezőkre bontás ===== public static void primtenyezosFelbontas(int szam) { int oszto = 2; while(szam > 1) { if(szam % oszto == 0) { System.out.printf("%20d|%d\n", szam, oszto); szam = szam / oszto; }else { oszto++; } } System.out.printf("%20d|\n", 1); } ===== Prímszámok tesztelése ===== Prímszám az, amelyiknek pontosan két osztója van a természetes számok között. Naiv módszer: public static boolean prim(long szam) { if(szam<2) return false; long i=szam-1; while( i>=Math.sqrt(szam) && ((szam % i) != 0) ) i--; if(i < Math.sqrt(szam)) return true; else return false; } Nagy számok esetén nem ad jó eredményt. Használják az [[w>Sieve_of_Eratosthenes|Eratoszthenész szitáját]], valószínűségi teszteket, és még néhány determinisztikus eljárást.