programozási tételekipari118-szerencs.sulinet.hu/jegyzet/info/programozási...programozási...
TRANSCRIPT
2015
PROGRAMOZÁSI TÉTELEK
Java nyelven
Nagy Zsolt
Informatika
Szakközépiskolai képzés
Programozási tételek 10 – 11. évfolyam
1. oldal
Tartalom Programozási tételek, algoritmusok ....................................................................................................................... 3
Feldolgozás végjelig ............................................................................................................................................ 3
Egy sorozathoz egy érték rendelése ........................................................................................................................ 4 Megszámlálás tétele ........................................................................................................................................... 4
Összegzés tétele ................................................................................................................................................. 5
Átlagszámítás tétele ........................................................................................................................................... 6
Eldöntés tétele .................................................................................................................................................... 7
Kiválasztás tétele ................................................................................................................................................ 9
Gyakorlás .......................................................................................................................................................... 10
Minimum- / Maximum-kiválasztás ................................................................................................................... 12
Keresés tétele ................................................................................................................................................... 13
Lineáris keresés: rendezetlen sorozatban ........................................................................................................ 16
Lineáris keresés: rendezett sorozatban ............................................................................................................ 18
Bináris keresés .................................................................................................................................................. 19
Egy sorozathoz egy sorozat rendelése .................................................................................................................. 22 Másolás ............................................................................................................................................................. 22
Kiválogatás ........................................................................................................................................................ 23
Egy sorozathoz több sorozat rendelése ................................................................................................................ 24 Szétválogatás .................................................................................................................................................... 25
Gyakorlás (másolás, kiválogatás, szétválogatás) .............................................................................................. 28
Rendezések, rendezettség .................................................................................................................................... 28 Rendezettség .................................................................................................................................................... 28
Minimum-kiválasztásos rendezés ..................................................................................................................... 30
Maximum kiválasztásos rendezés..................................................................................................................... 34
Gyakorlás .......................................................................................................................................................... 34
Buborék rendezés ............................................................................................................................................. 41
Beszúrásos rendezés ......................................................................................................................................... 45
Rendezések összehasonlítása ........................................................................................................................... 46
Minimum-kiválasztásos rendezés ................................................................................................................. 46
Buborék rendezés ......................................................................................................................................... 46
Javított Buborékos rendezés ......................................................................................................................... 46
Beszúró rendezés .......................................................................................................................................... 46
Gyorsrendezés .............................................................................................................................................. 47
Kupacrendezés .............................................................................................................................................. 47
Halmazműveletek ................................................................................................................................................. 47 Metszetképzés tétele ........................................................................................................................................ 49
Unióképzés tétele ............................................................................................................................................. 52
Programozási tételek 10 – 11. évfolyam
2. oldal
Különbség-képzés tétele ................................................................................................................................... 54
Rekurzió ................................................................................................................................................................ 56 Rekurzív függvények ......................................................................................................................................... 56
Rekurzív és iteratív forma ................................................................................................................................. 58
Gyorsrendezés (QuickSort) ............................................................................................................................... 60
Felhasznált és ajánlott irodalom ........................................................................................................................... 62
Programozási tételek 10 – 11. évfolyam
3. oldal
Programozási tételek, algoritmusok Az algoritmus különböző feladatok megoldására szolgáló utasítások jó szervezett együttesét
jelenti. Jellemzői: véges, determinisztikus, teljes.
Az informatikai programozási tételek olyan alap algoritmusokat jelentenek, amelyek
különböző típusfeladatok általános megoldásait adják. Ezeket kis átalakítással alkalmazhatjuk
egy konkrét feladat megoldása során.
Fajtái:
sorozathoz érték rendelése,
sorozathoz sorozat rendelése,
sorozathoz több sorozat rendelése,
több sorozathoz egy sorozat rendelése.
Feldolgozás végjelig
Egy feladat többszöri végrehajtása során, az ismétlések meghatározására három eset
különböztethető meg:
végtelen számú ismétlés nincs leállító feltétel
meghatározott számú ismétlés a leállító feltétel az adott érték meghaladása
feltételtől függő ismétlés végfeltétel alkalmazása.
Az utóbbi két esetben beszélhetünk végjelről, vagy végértékről. Ez a végjel fogja leállítani a
feldolgozást. A végjelet sosem dolgozzuk fel. Fontos, hogy a végjelnek választott érték, ne
essen a feldolgozandó adatok értelmezési tartományába.
Alapvetően előfeltételes ciklussal szokás megoldani. Ugyanis lehetővé kell tenni, hogy már az
első alkalommal végjelet kapunk, és nem a sorozat első értékes elemét.
Az alapelv a következő: A ciklus előtt beolvassuk az első adatot (lehet végjel is), majd
előfeltételes ciklus feltételében megvizsgáljuk, hogy nem végjel-e. Amennyiben nem,
feldolgozzuk az adatot, majd újra beolvasást alkalmazunk. Abban az esetben, ha végjelet
kapunk (ez lehet az első eset is), vége az ismétlésnek. A ciklust követő utasítással folytatjuk a
programot.
Programozási tételek 10 – 11. évfolyam
4. oldal
Algoritmus:
be: Adat
amíg Adat<>Végjel ismétel
Az adat feldolgozása
be: Adat
avége
Feladat:
Kérjük be egy kör sugarát, és számítsuk ki a kör területét és kerületét. A bekérést
addig végezzük, amíg a felhasználó nullát nem ad meg.
Egy sorozathoz egy érték rendelése Az algoritmus egy sorozatot dolgoz fel és egy értéket ad vissza.
Megszámlálás tétele
Adott egy N elemű A tömb. A feladat az, hogy számoljuk meg, hány T tulajdonságnak
megfelelő A(i) értéke van a tömbnek. Az A tömb elemek sorozatát tartalmazza. Az i értéke az
A tömb i. sorszámú értékét hivatkozza. A T(A(i)) tulajdonság (logikai függvény) egy {igaz,
hamis} értéket ad vissza, attól függően, hogy az A tömb i. értéke teljesíti-e a kitűzött feltételt.
A darabszámot egy Db változóban gyűjtjük.
A legegyszerűbb esetben a sorozat (A tömb) minden elemét megszámoljuk.
Algoritmus:
Db := 0
Ciklus i := 1-től N-ig
Ha T(A(i)) akkor Db := Db + 1
Ciklus vége
Ki: Db
Feladat:
Kérjünk be számokat nulla végjelig, majd határozzuk meg a darabszámot.
Feladat:
Határozzuk meg, hogy adott két szám között hány hárommal osztható szám van.
Pascal: szam MOD 3 = 0
Java: szam % 3 == 0
Feladat:
Határozzuk meg, hogy adott két szám között hány prímszám van.
Egy szám akkor prímszám, ha csak 1-el és önmagával osztható maradék nélkül. Az osztást
elég a szám négyzetgyökéig végezni.
Programozási tételek 10 – 11. évfolyam
5. oldal
Java kód:
package primek;
public class Primek {
public static void main(String[] args) {
//2000-től 20001-ig keressük meg a prímszámokat!
int primekszama = 0;
for (int n = 2000; n <= 20001; n++) {
int i = 2;
double sq = Math.sqrt(n);
while ((n%i != 0) && (i <= sq)) {
i++;
}
if (i > sq) {
primekszama++;
//Kiíratásnál csak 15 számot írunk egy sorba.
if (primekszama % 15 != 0){
System.out.print(n+", ");
}
else {
System.out.println();
System.out.print(n+", ");
}
}
}
System.out.println("");
System.out.println("Primek száma 2000 és 20000 között:
"
+primekszama+" darab.");
}
}
Összegzés tétele
Határozzuk meg egy számsorozat összegét. A számsorozatot egy N elemű A tömb
tartalmazza.
Algoritmus:
S := 0
Ciklus i := 1-től N-ig
S := S + A(i)
Ciklus vége
Ki: S
A sorozat összegét az S változó fogja tartalmazni, amit az összegzés előtt nullázni kell. A
sorozat elemein (az A tömbön), az i változó segítségével megyünk végig.
Feladat:
Olvassunk be számokat nulla végjelig, majd írjuk ki a számok összegét.
Az összegzéshez hasonló művelet még: A(i) elemek esetén, ahol A, a számokat tartalmazó
tömb, i = {1..N} természetes szám, az A tömb elemszáma.
a szorzat számítás: A(i)*A(i+1)*…*A(N-1)*A(N),
Programozási tételek 10 – 11. évfolyam
6. oldal
számtani közép (átlag) számítás: (A(i)+A(i+1)+…+A(N-1)+A(N)) / N
mértani közép: N√(A(i)*A(i+1)*…*A(N-1)*A(N)) N. gyök alatt egy szorzat
Feladat:
Számítsuk ki egy adott n nemnegatív egész szám faktoriálisát (n!).
Java-kód:
package faktorialis;
import java.util.Scanner;
public class Faktorialis {
public static void main(String[] args) {
Scanner be = new Scanner(System.in);
System.out.println("Faktoriális");
System.out.print("Szám: ");
int szam = be.nextInt();
int n;
//-1 végjelig folytatjuk
while(szam != -1){
if(szam < 0)
System.out.println("Csak nemnegatív számnak van
faktoriálisa!");
else {
n = fakt(szam);
System.out.println(szam+" faktoriálisa: "+n);
}
System.out.print("Szám: ");
szam = be.nextInt();
}
}
//Faktoriálist számító metódus
public static int fakt(int sz){
int n = 1;
if(sz == 0)
return 1;
else{
while(sz > 0){
n *= sz;
sz--;
}
return n;
}
}
}
Átlagszámítás tétele
Átlagszámításkor egyszerre kell elvégezni a megszámlálást és az összegképzést, majd
elosztani az összeget a darabszámmal. Viszont az átlagszámítást csak abban az esetben szabad
végrehajtani, ha volt átlagolandó adat, különben nullával osztanánk!
Programozási tételek 10 – 11. évfolyam
7. oldal
Feladat:
Határozzuk meg két felhasználótól bekért szám közötti páros / páratlan számok
átlagát.
Eldöntés tétele
Az eldöntés tételével egy adott tulajdonságú elem meglétét akarjuk bizonyítani. Adott egy N
elemű A tömb. Továbbá adjunk meg egy olyan T tulajdonságot (logikai függvényt), amely
{igaz} értékkel jelzi, ha az A tömbnek van ilyen eleme.
A T logikai függvény tehát akkor ad vissza {igaz} értéket, ha az A tömb 1..N elemei között
találunk megfelelő elemet.
Algoritmus:
i := 1
Ciklus amíg (i <= N) és nem T(A(i)) i := i + 1
Ciklus vége
Ki: (i <= N)
Az elemek vizsgálatát az első elemtől kezdjük (i := 1), és lépegetünk sorba az elemeken (i := i
+ 1), amíg el nem érjük a tömb végét (i <= N), vagy nem találunk T tulajdonságú elemet
(nem T(A(i))). A visszatérési érték akkor lesz igaz, ha nem értük el tömb végét (i <= N).
Feladat:
Döntsük el, hogy egy szavakat tároló tömbben van-e olyan szó, amely palindróma
(tükörszó). Java: String str;
str.equals((new StringBuilder(str)).reverse().toString());
Feladat:
Kérjünk be egész számokat nulla végjelig, és határozzuk meg, hogy van-e közöttük
négyzetszám.
Egy egész szám pontosan akkor négyzetszám, ha négyzetgyöke (létezik, és) egész. Minden
négyzetszám nemnegatív.1
Tízes számrendszerben a négyzetszámok a következő végződésűek lehetnek: 00, 1, 4, 6, 9
vagy 25 a következő szabályok szerint:
Ha a szám utolsó számjegye 0, akkor a négyzete 00 végződésű és az azt megelőző
számjegyek is négyzetszámot alkotnak.
1 https://hu.wikipedia.org/wiki/Négyzetszámok
Programozási tételek 10 – 11. évfolyam
8. oldal
Ha a szám utolsó számjegye 1 vagy 9, akkor a négyzete 1-re végződik és az azt
megelőző számjegyek 4-gyel osztható számot alkotnak.
Ha a szám utolsó számjegye 2 vagy 8, akkor a négyzete 4-re végződik és az azt
megelőző számjegyek páros számot alkotnak.
Ha a szám utolsó számjegye 3 vagy 7, akkor a négyzete 9-re végződik és az azt
megelőző számjegyek 4-gyel osztható számot alkotnak.
Ha a szám utolsó számjegye 4 vagy 6, akkor a négyzete 6-ra végződik és az azt
megelőző számjegyek páratlan számot alkotnak.
Ha a szám utolsó számjegye 5, akkor a négyzete 25-re végződik.
Java-kód:
package negyzetszam;
import java.util.Scanner;
import java.lang.Math;
public class NegyzetSzam {
public static void main(String[] args) {
Scanner be = new Scanner(System.in);
int szam;
System.out.println("Írj be egy számot, megmondom
nényzetszám-e!");
System.out.print("Szám = ");
while((szam = be.nextInt()) != 0){
if(isNegyzetSzam(szam))
System.out.println("Négyzetszám");
else
System.out.println("Nem négyzetszám");
System.out.print("Szám = ");
}
}
//logikai függvény
public static boolean isNegyzetSzam(int sz){
int e;
double d;
if(sz >= 0){
d = Math.sqrt(sz);
e = (int) Math.round(d);
return (e * e == sz);
}
else {
return false;
}
}
}
Programozási tételek 10 – 11. évfolyam
9. oldal
Kiválasztás tétele
A kiválasztás tételével keresünk egy adott T() tulajdonsággal rendelkező elemet, vagy annak
az indexét (helyét a sorozaton belül). Tudjuk, hogy a tömbnek van T() tulajdonságú eleme. A
sorozatot egy N elemszámú A tömb reprezentálja. A T() függvény {igaz} értéket ad, ha a
sorozat i. eleme adott tulajdonságú.
Algoritmus:
i := 1
Ciklus amíg nem T(A(i))
i := i + 1
Ciklus vége
Ki: i, A(i)
A visszatérési érték tehát az A tömb i. eleme, vagy annak A(i) értéke.
Feladat:
70 és 200 között melyik az első 9-cel osztható szám. (Kilenccel osztható a szám, ha a
számjegyek összege osztható 9-cel.)
Java-kód:
package oszthatokilenc;
public class OszthatoKilenc {
public static void main(String[] args) {
System.out.println("A program 70 - 200 között megkeresi
"
+ "az első 9-cel osztható számot.");
for(int i = 70; i<= 200; i++){
if(isOszthatoKilenc(i)){
System.out.println("Az első kilenccel osztható
szám: "+i);
break;
}
}
}
public static boolean isOszthatoKilenc(int szam){
int m, ossz = 0;
while(szam != 0){
m = szam % 10;
szam /= 10;
ossz += m;
}
return (ossz % 9) == 0;
}
}
Feladat:
Határozzuk meg egy számtani sorozat mediánját (középértékét).
Programozási tételek 10 – 11. évfolyam
10. oldal
Véges elemszámú sokaság esetén a medián a sorba rendezett adatok közül a középső érték;
vagy másképpen: a medián az az érték, amely a sorba rendezett adatokat két egyenlő részre
osztja. Ha a sokaság elemeinek száma páratlan, akkor az iménti meghatározás egyértelmű,
mert akkor van egy középső adat, amely előtt ugyanannyi adat van, mint utána. Páros számú
elem esetén két középső adat van, ez esetben a kettő közti bármelyik érték mediánnak
tekinthető. A gyakorlatban a két érték számtani közepét szokták megadni.2
Páratlan elemszám esetén:
1 2 5 4 3 1 4 3 3 4 3 5 1
A rendezett sokaság:
1 1 1 2 3 3 3 3 4 4 4 5 5
A medián a középső elem:
1 1 1 2 3 3 3 3 4 4 4 5 5
Páros elemszám esetén:
1 4 2 4 2 3 5 3 1 1
A rendezett sokaság:
1 1 1 2 2 3 3 4 4 5
A medián a középső elemek számtani közepe: 2,5.
Gyakorlás
Feladat:
Határozzuk meg két szám legnagyobb közös osztóját.
Leírás:3
Két (nem egyszerre nulla) egész szám közös osztói közül a lehetséges legnagyobb nem nulla
pozitív egész, amely mindkét egész számot (maradék nélkül) osztja.
Az euklideszi algoritmus egy számelméleti algoritmus, mellyel két szám legnagyobb közös
osztója határozható meg.
Legyen:
2 https://hu.wikipedia.org/wiki/Medián 3 Forrás: http://hu.wikipedia.org/wiki/Euklideszi_algoritmus
Programozási tételek 10 – 11. évfolyam
11. oldal
Az algoritmus első lépésében maradékosan osztjuk -t -vel, a második lépésben -t a
maradékkal, majd az előbbi maradékot az új maradékkal, és így tovább, mindig az osztót a
maradékkal.
Így a következő lépéssorozatot kapjuk:
ahol
A maradék véges sok lépés után nulla lesz, hiszen amíg nem nulla, addig minden lépésben
legalább eggyel csökkenni fog, tehát az utolsó lépésnél:
A keresett legnagyobb közös osztó az , azaz az utolsó nem nulla maradék.
Példa:
A 360 és a 225 legnagyobb közös osztójának meghatározása az euklideszi algoritmussal:
Tehát a legnagyobb közös osztó a 45.
Java-kód:
package lnkoeuklidesz;
import java.util.Scanner;
public class LnkoEuklidesz {
public static void main(String[] args) {
Scanner be = new Scanner(System.in);
System.out.println("LNKO meghatározása");
System.out.print("első szám: ");
int szam1 = be.nextInt();
System.out.print("második szám: ");
int szam2 = be.nextInt();
int kozos = lnko(szam1, szam2);
if(kozos > 0)
System.out.println("A két szám közös
osztója:"+kozos);
Programozási tételek 10 – 11. évfolyam
12. oldal
else
System.out.println("A két számnak nincs közös
osztója.");
}
//0 visszatérési érték jelzi, hogy nincs közös osztó.
public static int lnko(int szam1, int szam2){
int m;
if(szam1 < szam2){
//szam1 és szam2 megcserélése kizáró vagy
művelettel (^)
szam1 = szam1 ^ szam2;
szam2 = szam1 ^ szam2;
szam1 = szam1 ^ szam2;
}
//Az osztó nem lehet nulla.
if(szam2 == 0)
return 0;
// szam1 >= szam2
m = szam1 % szam2;
while(m != 0){
szam1 = szam2;
szam2 = m;
m = szam1 % szam2;
}
return szam2;
}
}
Feladat:
Számoljuk meg, hogy egy életkorokat tartalmazó tömbben hány 10 évnél fiatalabb,
tizenéves, huszonéves, … ember adata van.
Feladat:
Olvassunk be osztályzatokat 0 végjelig, és számoljuk meg, hogy hány ötös, négyes,
hármas, kettes, illetve egyes volt közöttük.
Minimum- / Maximum-kiválasztás
Minimum-kiválasztás esetén egy A sorozat legkisebb, maximum-kiválasztásnál a legnagyobb
elemét A(i) kell meghatározni.
Minimum-kiválasztásnál az algoritmus lényege, hogy az elemeket sorban megvizsgáljuk nem
kisebb-e, mint az addigi legkisebbnek tartott elem. Ha találtunk egy kisebb elemet, akkor
megjegyezzük. Induló minimális elemnek, vagy a sorozat első elemét A(1) vesszük, vagy egy
olyan értéket, amitől a sorozat minden eleme csak kisebb lehet A(i) < MIN, ahol i a sorozat
elemeinek indexe, i 1..N.
Programozási tételek 10 – 11. évfolyam
13. oldal
Algoritmus:
MinIndex := 1
Ciklus i := 2-től N-ig
Ha A(i) < A(MinIndex) akkor
MinIndex := i
Ha vége
Ciklus vége
Ki: MinIndex, A(MinIndex)
Feladat:
Generáljunk véletlen számokat, amelyek egy téli hónap éjszakai hőmérsékleti értékeit
jelentik. (pl. -20..-5) Határozzuk meg a leghidegebb értéket, és azt, hogy ez hányadik
napja volt a hónapnak! (Véletlen szám 0-15-ig mínusz 20.)
Java-kód:
package leghidegebb;
import java.util.Random;
public class LegHidegebb {
public static void main(String[] args) {
Random rnd = new Random();
int [] honap = new int [30];
//véletlen számok generálása -20..-5
for(int i = 0; i < honap.length; i++){
honap[i] = rnd.nextInt(16)-20;
}
//hőmérsékletek kiíratása
System.out.print("A hónap hőmérsékleteti: ");
for(int i = 0; i < honap.length; i++)
System.out.print(honap[i]+", ");
System.out.println("");
//leghidegebb nap kiválasztása
int mini = 0;
for(int i = 1; i < honap.length; i++ ){
if(honap[i] < honap[mini])
mini = i;
}
System.out.println("A leghidegebb nap: "+mini);
System.out.println("A leghidgebb hőmérséklet:
"+honap[mini]);
}
}
Keresés tétele
Adott egy N elemű A tömb, valamint egy T() tulajdonság (logikai függvény). Döntsük el,
hogy van-e az A tömbnek T tulajdonságú eleme. Ha van, adjuk meg az elemet, vagy az elem
tömbbeli indexét!
Algoritmus:
i := 1
Programozási tételek 10 – 11. évfolyam
14. oldal
Ciklus amíg (i <= N) és nem T(A(i))
i := i + 1
Ciklus vége
Ha (i <= N) akkor
Ki: i, A(i)
különben
Ki: hamis
Elágazás vége
Az elemek vizsgálatát az első elemtől kezdjük (i := 1), és lépegetünk sorba az elemeken (i := i
+ 1), amíg el nem érjük a tömb végét (i <= N), vagy nem találunk T tulajdonságú elemet
(nem T(A(i))). Ha nem értük el tömb végét (i <= N), akkor találtunk T tulajdonságú elemet,
így ezt, illetve ennek indexét adjuk vissza, egyéb esetben hamis logikai értékkel tér vissza.
Feladat:
A felhasználótól bekért számsorozatban melyik volt és hányadik az első 6-tal osztható
szám. (Hattal osztható egy szám, ha osztható 2-vel és 3-mal is.) Nulla végjelig!
Java-kód:
package kereses6oszthato;
import java.util.Scanner;
public class Kereses6Oszthato {
public static void main(String[] args) {
Scanner be = new Scanner(System.in);
System.out.println("Keressük az első hattal osztható
számot!");
System.out.print("szám: ");
int szam = be.nextInt();
// !((szam % 2 == 0) && (szam % 3 == 0)) -->
//(szam % 2 != 0) || (szam % 3 != 0)
// 0-ra kilépés
while(((szam % 2 != 0) || (szam % 3 != 0))
&& (szam != 0)){
System.out.print("szám: ");
szam = be.nextInt();
}
//Miért hagytuk el a ciklust?
if(szam != 0)
System.out.println("Az első hattal osztható szám:
"+szam);
else
System.out.println("Nem adtunk meg hattal osztható
számot!");
}
}
Feladat:
A felhasználótól bekért számsorozatban melyik volt és hányadik az első 5-tel osztható
szám. (Öttel osztható egy szám, ha utolsó helyen 0 vagy 5 számjegy áll.)
Programozási tételek 10 – 11. évfolyam
15. oldal
Feladat:
A felhasználótól bekért számsorozatban melyik volt és hányadik az első 25-tel
osztható szám. (Huszonöttel osztható, ha az utolsó két helyen 0 áll, vagy ha az utolsó
két számjegy osztható 25-tel.)
Feladat:
A felhasználótól bekért számsorozatban melyik volt és hányadik az első 9-cel osztható
szám. (Kilenccel osztható a szám, ha a számjegyek összege osztható 9-cel.)
Java-kód:
package oszthato;
import java.util.Scanner;
public class Oszthato {
public static void main(String[] args) {
Scanner be = new Scanner(System.in);
int szam, sorszam = 0;
boolean megvan = false;
System.out.println("Melyik és hányadik az első kilencel
osztható szám?");
System.out.print("Szám = ");
szam = be.nextInt();
while((szam != 0) && !megvan){
if(isOszthatoKilenc(szam)){
sorszam++;
megvan = true;
System.out.println("A(z) "+sorszam+". szám:
"+szam+" osztható"
+ " kilencel.");
}
else{
sorszam++;
System.out.print("Szám = ");
szam = be.nextInt();
}
}
if(!megvan)
System.out.println("Eddig nem volt 9-cel osztható
szám.");
}
//kilencel osztható, ha a számjegyek összge osztható
kilencel
private static boolean isOszthatoKilenc(int sz){
int ossz = 0;
while(sz != 0){
ossz += sz % 10;
sz = sz / 10;
}
return ossz % 9 == 0;
}
}
Programozási tételek 10 – 11. évfolyam
16. oldal
Lineáris keresés: rendezetlen sorozatban
Adott N elemszámú sorozatban keressük a T() tulajdonsággal rendelkező elemet. Az elemeket
sorban, a sorozat elejétől egyesével vizsgáljuk. Mivel a sorozat a kereső tulajdonság szerint
nincs rendezve, ezért nem tudjuk benne van-e a keresett elem, és hol. A keresést leállító
feltétel kétféle lehet:
Egy elemet tartalmaz a sorozat, akkor az elem megtalálásáig, vagy, ha nincs benne,
akkor a sorozat végéig keresünk.
Több elem esetén, ha szükségünk van minden elemre, akkor szintén a sorozat végéig
kell keresni. Amennyiben nincs szükség minden elemre, akkor általában az első elem
megtalálása után vége a keresésnek.
A lineáris keresést hívják még szekvenciális keresésnek is.
Az összehasonlítások száma N elem estén minimum 1, maximum N, átlagban (N+1)/2.
Az, hogy a keresett elem nincs benne a sorozatban, csak az utolsó összehasonlítás után derül
ki.
Algoritmus:
változó I, Hely:egész
változó Adat: ElemTípus
változó Talált: logikai
I:=1
Ciklus amíg (I<=N) és (A[I]<>Adat) ismétel
I:=I+1
Ciklus vége
Talált := I<=N
Ha Talált akkor
Hely:=I
Ha vége
Feladat:
Generáljunk véletlen számokat -20 °C és +35 °C között, majd keressük meg benne az
első olyan hőmérsékletet, amelyiket a felhasználótól kértük be.
Java-kód:
package lineariskeresesrendezetlen;
import java.util.Scanner;
import java.util.Random;
public class LinearisKeresesRendezetlen {
public static void main(String[] args) {
Random rnd = new Random();
Scanner be = new Scanner(System.in);
//Véletlen számok generálása -20..+35.
Programozási tételek 10 – 11. évfolyam
17. oldal
int tomb[] = new int[20];
for(int i = 0; i < tomb.length; i++)
tomb[i] = rnd.nextInt(56)-20;
//lista
System.out.println("A tömb elemei:");
for(int i = 0; i < tomb.length; i++)
System.out.print(tomb[i]+", ");
System.out.println("");
//mit keressek
System.out.print("Kérem a számot, amit meg kell
keresnem: ");
int szam = be.nextInt();
//keresés
int i = 0;
while((i < tomb.length) && (tomb[i] != szam))
i++;
//miért hagytuk el a tömböt
if(i < tomb.length)
System.out.println("Benne van, helye: "+
(i+1)+".");
else
System.out.println("Nincs benne!");
}
}
Futási kép:
run:
A tömb elemei:
5, -17, 12, 14, 22, 1, 20, 20, 8, -20, 1, 21, 13, -20, 4, -19,
15, 29, -16, 33,
Kérem a számot, amit meg kell keresnem: 1
Benne van, helye: 6.
BUILD SUCCESSFUL (total time: 3 seconds)
A pirossal szedett részt nézzük meg alaposabban! Annak az eldöntését, hogy egy elem benne
van-e a sorozatban, a ciklusból kilépve kell megvizsgálni. Logikusabbnak gondolhatnánk a
vizsgálatot, ha a tömb adott elemét a bekért számmal hasonlítanánk össze.
A következő módon:
//miért hagytuk el a tömböt
if(tomb[i] == szam)
System.out.println("Benne van, helye: "+
(i+1)+".");
else
System.out.println("Nincs benne!");
Helyes eredményt kapunk, ha a keresett elem benne van a sorozatban. Amennyiben a keresett
elem nincs benne, hibajelzést kapunk.
Futási kép:
A tömb elemei:
Programozási tételek 10 – 11. évfolyam
18. oldal
3, -8, 7, 17, -8, 12, -19, -15, 12, 14, -16, 28, 27, -13, -20,
15, -14, 31, -2, 5,
Kérem a számot, amit meg kell keresnem: 40
Exception in thread "main"
java.lang.ArrayIndexOutOfBoundsException: 20
at
lineariskeresesrendezetlen.LinearisKeresesRendezetlen.main(Line
arisKeresesRendezetlen.java:38)
Java Result: 1
BUILD SUCCESSFUL (total time: 5 seconds)
Gondoljuk végig a ciklus működését! Mivel nincs benne a keresett elem a sorozatban, ezért
végig keresünk. A ciklus utolsó lépésében a ciklusváltozó értéke nagyobb, mint a tömb
elemszáma (i > tomb.length). Ez pedig túlindexelést eredményez, és hibát generál!
Lineáris keresés: rendezett sorozatban
A sorozatnak rendezettnek kell lenni. Az előzőhöz képest növeli a hatékonyságot, hogy akkor
is leáll a keresés, ha nagyobb elemre lépünk, mint a keresett érték.
Algoritmus:
változó I, Hely:egész
változó Adat: ElemTípus
változó Talált: logikai
I:=1
Ciklus amíg (I<=N) és (A[I]<Adat) ismétel
I:=I+1
Ciklus vége
Talált := (I<=N) és (A[I]=Adat)
Ha Talált akkor
Hely:=I
Ha vége
Feladat:
Generáljunk 20 véletlen egész számot, az 5..50 tartományból. Rendezzük nagyság
szerint, majd keressünk meg benne egy felhasználó által megadott számot.
Java-kód:
package lieariskeresrendezett;
import java.util.Scanner;
import java.util.Random;
// tömbökkel kapcsolatos metódusok, pl. rendezések
import java.util.Arrays;
public class LiearisKeresRendezett {
public static void main(String[] args) {
// Deklarációk
Scanner be = new Scanner(System.in);
int [] tomb = new int [20];
// tömb feltöltése véletlen számokkal
feltoltVeletlen(tomb);
Programozási tételek 10 – 11. évfolyam
19. oldal
// tömb listázása rendezés előtt
System.out.println("A véletlen számok rendezés
előtt:");
lista(tomb);
// tömb rendezése
Arrays.sort(tomb);
// tömb listázása rendezés után
System.out.println("A véletlen számok rendezés után:");
lista(tomb);
// szám bekérése
System.out.print("Mit keressek: ");
int szam = be.nextInt();
// keresés rendezett tömbben
// ha nincs benne az eredmény -1, egyébként az index
int eredmeny = keres(tomb, szam);
if(eredmeny < 0)
System.out.println("Nincs benne!");
else
System.out.println("A keresett elem indexe:
"+eredmeny);
}
// tömb feltöltését elvégző metódus 5..50 közötti számokkal
public static void feltoltVeletlen(int[] t){
Random rnd = new Random();
for(int i = 0; i < t.length; i++){
t[i] = rnd.nextInt(46)+5;
}
}
// tömb listázása
public static void lista(int[] t){
for(int i = 0; i < t.length; i++){
System.out.print(t[i]+", ");
}
System.out.println("");
}
// keresés a tömbben, ha -1 nincs benne, egyébként az index
public static int keres(int[] t, int sz){
int i = 0;
while((i < t.length) && (t[i] < sz))
i++;
if((i < t.length) && (sz == t[i]))
return i;
else
return -1;
}
}
Az Arrays osztályban sok tömbökön dolgozó metódus van definiálva, pl. a rendezések
különböző típusú adatokon.
Bináris keresés
Adott egy N elemű, rendezett A sorozat. Keressük meg benne az X értéket!
Programozási tételek 10 – 11. évfolyam
20. oldal
A keresés maximális időigénye log2(N), N az elemszám, ezért nevezik a keresést logaritmikus
keresésnek. Minél nagyobb az elemszám, annál jobban megmutatkozik az algoritmus
hatékonysága. Például 1024 elemszámnál log2(1024)=10, azaz maximum 10 lépésen belül
megvan az elem vagy kiderül, hogy nincs benne.
Algoritmus:
Logaritmikus(be:tömb[1..N], be:keresett, ki: sorszám)
Deklaráció
alsó, felső: egész
Logaritmus kezdet
alsó:=1
felső:= N
Ciklus
sorszám:= (alsó + felső) DIV 2
Ha keresett > tömb[sorszám] akkor
alsó:= sorszám + 1
Ha vége
Ha keresett < tömb[sorszám] akkor
felső:= sorszám – 1
Ha vége
Mígnem (tömb[sorszám] = keresett) VAGY (alsó > felső)
Ciklus vége
Ha alsó > felső akkor
sorszám := -1
Ha vége
Logaritmikus vége
Fontos megérteni, hogy ez az általános algoritmus a végfeltételes ciklusnál kilépési feltételt
fogalmaz meg. Az általunk használt Java nyelv végfeltételes ciklusa pedig belépési feltételt
használ.
De-Morgan azonosságok, amennyiben szükséges:
nem (a és b) = (nem a) vagy (nem b),
nem (a vagy b) = (nem a) és (nem b)
Feladat:
Töltsünk fel egy tömböt véletlen számokkal, majd keressünk meg benne egy
felhasználó által megadott számot.
package binariskereses;
import java.util.Arrays;
import java.util.Random;
import java.util.Scanner;
public class BinarisKereses {
public static void main(String[] args) {
Programozási tételek 10 – 11. évfolyam
21. oldal
System.out.println("Bináris keresés feladat.");
int[] tomb = new int[20];
//Véletlen számok generálása - mibe, alsó, felső érték
randomGenerator(tomb, 0, 100);
//Számok kiíratása rendezetlenül
System.out.println("Rendezetlen lista:");
lista(tomb);
//Rendezés az Arrays osztály statikus sort()
metódusával.
Arrays.sort(tomb);
//Rendezett lista
System.out.println("Rendezett lista:");
lista(tomb);
//Kereséshez adat bekérés
System.out.print("Kérem a számot: ");
Scanner be = new Scanner(System.in);
int keresett = be.nextInt();
//Bináris keresés
int eredmeny = binSearch(tomb, keresett);
if(eredmeny == -1){
System.out.println("Nincs benne a keresett
érték.");
}
else{
System.out.println("Index: "+eredmeny);
}
........//Keresés az Arrays tömb beépített függvényével
eredmeny = Arrays.binarySearch(tomb, keresett);
System.out.println("\nKeresés eredménye az Arrays
beépített függvényével.");
if(eredmeny == -1){
System.out.println("Nincs benne a keresett
érték.");
}
else{
System.out.println("Index: "+eredmeny);
}
}
//Tömb feltöltése véletlen számmal.
public static void randomGenerator(int [] t, int also, int
felso){
Random rnd = new Random();
for(int i = 0; i < t.length; i++){
t[i] = rnd.nextInt(felso-also+1)+also;
}
}
//Tömb listázása.
public static void lista(int [] t){
for(int i = 0; i < t.length; i++){
System.out.print(t[i]+", ");
if((i+1) % 10 == 0)
System.out.println("");
}
System.out.println("");
}
Programozási tételek 10 – 11. évfolyam
22. oldal
//Bináris keresés függvénye, -1 ha nincs benne egyébként az
index.
public static int binSearch(int[] t, int keresett){
int also = 0;
int felso = t.length-1;
int kozepso;
do{
kozepso = (also + felso) / 2;
if(keresett < t[kozepso])
felso = kozepso - 1;
else if(keresett > t[kozepso])
also = kozepso + 1;
}while((t[kozepso] != keresett) && (also <= felso));
if(also <= felso)
return kozepso;
else
return -1;
}
}
Egy sorozathoz egy sorozat rendelése Az algoritmus bemenete egy sorozat, a kimenete szintén egy sorozat. A kimeneti sorozat lehet
szűkebb, egyező, vagy bővebb, mint a bemeneti. Az elemeken különböző transzformációt is
végezhetünk.
Másolás
Egy bemenő sorozatból egy kimenő sorozatot készítünk, mégpedig úgy, hogy az
eredménysorozat ugyanolyan elemszámú, mint a bemeneti sorozat, és az eredménysorozat I.
tagját a bemenő sorozat I. tagjából lehet meghatározni. A bemenő sorozatot tehát átmásoljuk
úgy, hogy közben az elemeken esetleges átalakításokat végzünk.
Algoritmus:
Ciklus I:=1..NBemenő ismétel
Bemenő sorozat I. eleméből Kimenő sor I. elemének előállítása
Ciklus vége
Feladat:
A születési éveket tartalmazó tömbből hozzunk létre egy tömböt, mely az életkorokat
tartalmazza.
Feladat:
Töltsünk fel véletlen számokkal egy 20 elemű tömböt úgy, hogy az elemek 1000 és
5000 közöttiek legyenek. Ez legyen például könyvek nettó ára. Számoljuk ki a bruttó
árakat egy másik tömbbe (ÁFA: 27%).
Programozási tételek 10 – 11. évfolyam
23. oldal
Java-kód:
package masolnettobrutto;
import java.util.Random;
import java.lang.Math;
public class MasolNettoBrutto {
public static void main(String[] args) {
// deklarációk
int[] netto = new int[20];
int[] brutto = new int[20]; // egész értékekkel
// nettó értékek feltöltése 1000..5000 között
Random rnd = new Random();
for(int i = 0; i < netto.length; i++)
netto[i] = rnd.nextInt(4001)+1000;
// másolás transzformációval - bruttó előállítása
for(int i = 0; i < brutto.length; i++)
brutto[i] = (int)Math.round(netto[i] * 1.27);
//nettó, bruttó ár listázása
System.out.println("A könyvek nettó árai:");
lista(netto);
System.out.println("A könyvek bruttó árai:");
lista(brutto);
}
// Listázó metódus
public static void lista(int[] t){
for(int i = 0; i < t.length; i++)
System.out.print(t[i]+", ");
System.out.println("");
}
}
Kiválogatás
Adott egy N elemű A tömb és egy T() tulajdonság. Válogassuk ki egy B tömbbe az A vektor
T() tulajdonságú elemeit. A két tömb elemszámának meg kell egyezni, mert lehet, hogy az első
tömb minden elemét át kell másolni.
Algoritmus:
Db := 0
Ciklus i := 1-től N-ig
Ha T(A(i) akkor
Db := Db + 1
B(Db) := A(i)
Ha vége
Ciklus vége
Feladat:
Töltsünk fel egy String tömböt nevekkel, majd válogassuk ki egy másik tömbbe a K,
L, M betűkkel kezdődő neveket.
Java-kód:
package kivalogatastetele;
public class KivalogatasTetele {
Programozási tételek 10 – 11. évfolyam
24. oldal
public static void main(String[] args) {
// deklaráció kezdőértékadással
String[] nevek = {"Ákos", "Béla", "Zénó", "Mátyás",
"Eszter", "Leopold", "Géza", "Éva", "Laura", "Mária"};
// nevek kiíratása
kiir(nevek, nevek.length);
// a két tömb elemszámának meg kell egyezni
String[] nevek2 = new String[10];
// K,L,M betűkkel kezdődő nevek kiválogatása
// nevek2 indexváltozója -1, mert lehet, hogy egy sem
egyezik
int j = -1;
for(int i = 0; i < nevek.length; i++)
if(isEgyezik(nevek[i])){
j++;
nevek2[j] = nevek[i];
}
// Ha volt K, L, M kezdőbetűjű név, akkor kiírjuk.
if(j > -1)
kiir(nevek2, j);
else
System.out.println("Nincs K, L, M kezdőbetűvel
név.");
}
// isEgyezik metódus megvizsgálja a nevek első betűjének
egyezőségét
public static boolean isEgyezik(String nev){
return (nev.charAt(0) == 'K')||(nev.charAt(0) == 'L')
||(nev.charAt(0) == 'M');
}
// nevek kiíratása
public static void kiir(String[] n, int db){
System.out.println("Nevek:");
for(int i = 0; i < db; i++){
System.out.print(n[i]+", ");
// minden ötödik név után sort emel
if((i+1) % 5 == 0)
System.out.println("");
}
System.out.println("");
}
}
Feladat:
Töltsünk fel véletlen számokkal egy 20 elemű tömböt úgy, hogy az elemek 10 és 100
közöttiek legyenek. Válogassuk ki a 10-zel osztható számokat egy másik tömbbe.
Egy sorozathoz több sorozat rendelése Van egy bemeneti és több kimeneti sorozat.
Programozási tételek 10 – 11. évfolyam
25. oldal
Szétválogatás
Egy bemenő sorozatból több kimenő sorozatot készítünk. Azok a feladatok tartoznak ide,
amelyeknél a bejövő adatok mindegyikére szükségünk van ugyan, de azokat valamilyen
szempontból el kell különíteni, szét kell válogatni. A kimenő sorozatok elemszámainak
összege megegyezik a bemenő sorozat elemszámával. A szétválogatást fel lehet fogni több
egymás utáni kiválogatásként is, ahol egyszer minden elemre sor kerül. Mindegyik
eredménysorozatban ugyanannyi elemszámra kell felkészülni, mint a bemenő sorozat
elemszáma, hiszen szélsőséges esetben elképzelhető, hogy minden elem egyetlen kimenő
sorozatba kerül át.
Algoritmus:
Eljárás szétválogatás
NBemenő // bemeneti sorozat elemszáma
NKimenő1:=0 // első kimeneti sorozat elemszáma
NKimenő2:=0 // második kimeneti sorozat elemszáma
... // szükség esetén további kimeneti sorozatok
ciklus I:=1..NBemenő ismétel
elágazás
amikor Bemenő[I] az 1. tulajdonságú:
NKimenő1:=NKimenő1+1
Kimenő1[NKimenő1]:=Bemenő[I]
amikor Bemenő[I] az 2. tulajdonságú:
NKimenő2:=NKimenő2+1
Kimenő2[NKimenő2]:=Bemenő[I]
...
különben
...
elágazás vége
Ciklus vége
Eljárás vége
Feladat:
Adott egy osztály névsor. Válogassuk szét a tanulókat nemük szerint két csoportba. A
Tanulo osztály tartalmaz egy ffi adattagot, a fiú/lány – igaz/hamis jelölésére.
Java-kód:
package szetvalogattanulo;
import java.util.Scanner;
public class SzetvalogatTanulo {
public static void main(String[] args) {
// Kapcsolat létrahozása a Tanulo osztállyal.
// tárolás tömbben
Tanulo[] tanulok = new Tanulo[10];
// a tanulok tömb feltöltése
feltolt(tanulok);
// lista a tanulókról
System.out.println("A tanulók listázása:");
lista(tanulok, tanulok.length);
Programozási tételek 10 – 11. évfolyam
26. oldal
// két nemek szerinti tömb létrehozása
Tanulo[] ferfiak = new Tanulo[10];
Tanulo[] nok = new Tanulo[10];
// elemszám a lányok és férfiak tömbjeihez
// tömbben tárolva a referencia miatt
// első elem férfi, második a nők száma
int[] letszam = new int[2];
letszam[0] = 0;
letszam[1] = 0;
// nemek szerinti szétválogatás
szetvalogat(tanulok, ferfiak, nok, letszam);
// nemek szinti listázás, ha volt elem
System.out.println("Lányok listázása:");
if(letszam[1] > 0)
lista(nok, letszam[1]);
else
System.out.println("Nem voltak lányok");
System.out.println("Fiúk listázása:");
if(letszam[0] > 0)
lista(ferfiak, letszam[0]);
else
System.out.println("Nem voltak fiúk");
}
// tanulok tömb feltöltése
public static void feltolt(Tanulo[] t){
Scanner be = new Scanner(System.in);
System.out.println("A 10 elemű tanulók tömb
feltöltése");
String nev;
char ffi;
for(int i = 0; i < t.length; i++){
System.out.print("Név: ");
nev = be.nextLine();
System.out.print("Férfi-e (f/n): ");
ffi = be.nextLine().charAt(0);
t[i] = new Tanulo(nev, ffi);
}
}
// lista
public static void lista(Tanulo[] t, int letszam){
System.out.println("Név\t\tNeme");
for(int i = 0; i < letszam; i++){
System.out.printf("%10s\t%3c\n",t[i].getNev(),
t[i].getFerfi());
}
}
// szétválogatás nemek szerint
public static void szetvalogat(Tanulo[] t, Tanulo[] f,
Tanulo[] n, int[] l){
for(int i = 0; i < t.length; i++){
if(t[i].getFerfi() == 'f'){
// férfiak elemszámának növelése
l[0]++;
// elhelyezés a fiúk tömbjébe
// az index elemszam-1
Programozási tételek 10 – 11. évfolyam
27. oldal
f[l[0]-1] = new Tanulo(t[i].getNev(),
t[i].getFerfi());
}
else if(t[i].getFerfi() == 'n'){
// nők elemszámának növelése
l[1]++;
// elhelyezés a lányok tömbjébe
// az index elemszám-1
n[l[1]-1] = new Tanulo(t[i].getNev(),
t[i].getFerfi());
}
}
}
}
A Tanulo osztály: package szetvalogattanulo;
public class Tanulo {
// adattagok
String nev;
char ffi; //f - férfi, n - nő
// konstruktor
public Tanulo(String nev, char ffi){
// A this objektumreferencia szükséges, mert a lokális
// változók takarják az osztály szintű változókat.
this.nev = nev;
this.ffi = ffi;
}
//setter (beállító) metódusok
public void setNev(String n){
// Mivel a lokális szinten lévő paraméter nem takarja
// az osztály adattagot, nem szükséges this előtag.
nev = n;
}
public void setNeme(char n){
ffi = n;
}
// getter (lekérdező) metódusok
public String getNev(){
return nev;
}
public char getFerfi(){
return ffi;
}
}
Feladat:
Állítsunk elő egy 20 elemű véletlen egészeket [0..100] tartalmazó sorozatot, majd
válogassuk szét a páros és a páratlan számokat.
Programozási tételek 10 – 11. évfolyam
28. oldal
Gyakorlás (másolás, kiválogatás, szétválogatás)
Feladat:
Adott egy neveket (vezeték és keresztnév) tartalmazó szóközzel elválasztott tömb. A
vezeték és keresztnevek szóközzel vannak elválasztva. Állítsuk elő a monogramokat
tartalmazó tömböt. A kiíratásokat végezzük el.
Feladat:
Adott egy dolgozók nevét és fizetését tartalmazó vektor. Válogassuk ki azon dolgozók
neveit, akiknek a fizetése kisebb, mint 120000 Ft.
Feladat:
Egy iskola sportolási lehetőséget biztosít a tanulóinak. Háromféle lehetőség közül
választhatnak a diákok (futball, ping-pong, kosárlabda). Egyet kötelezően választani
kell. A tanulóknál nyílván tartják, hogy ki mit választott. Készíts listát, amelyben
szétválogatjuk a tanulókat a sport csoportoknak megfelelően.
Rendezések, rendezettség Rendezésnek nevezünk egy algoritmust, ha az valamilyen szempont alapján sorba állítja
elemek egy listáját.
Legyen adott egy N elemszámú A sorozat. A rendezés feladata, hogy a sorozat A(i) és A(i+1)
elemeit a rendező elv R(A(i), A(i+1)) szerinti sorrendbe tegye.
A legegyszerűbb esetben növekvő rendezést végzünk. Tehát az R(A(i), A(i+1)) rendezettség
(logikai) függvény igaz értékkel tér vissza, ha az A(i) értéke kisebb egyenlő, mint az A(i+1)
értéke.
Rendezettség
A rendezettség azt jelenti, hogy egy sorozat egymást követő két eleméről (pl. A és B)
egyértelműen meg lehet állapítani, hogy melyikük az előrébb való. A rendező elv lehet
bonyolultabb is, mint a kisebb/nagyobb reláció. Amikor egy összetett feltétel szerint kell
meghatározni az elemek egymáshoz viszonyított helyét, érdemes egy rendező függvényt
készíteni. Ez a függvény, akkor fog igazat visszaadni, ha a két rendezendő elem
egymáshoz képest jó helyen van.
Rendező függvény:
Rendezett(A(i), A(i+1)): logikai
return A(i) <= A(i+1)
Programozási tételek 10 – 11. évfolyam
29. oldal
Rendezett vége
Feladat:
Töltsünk fel egy 20 elemű vektort véletlen értékekkel, és rendezzük úgy, hogy elől
legyenek a páratlan számok növekvően, majd a párosak szintén növekvő sorrendben!
Rendező elv (feltétel) meghatározása:
Azokat a feltételeket kell megtalálni, amelyek szükségesek a rendezettség előállításához.
Legyen A az első, B a második szám az R(A, B) rendező függvénynél:
A páratlan, B páros,
Ha A és B páratlan, akkor A < B,
Ha A és B páros, akkor A < B.
Nézzük a relációkat:
Páratlanság vizsgálata: (A % 2 != 0) – a szám kettővel való osztása nem nulla osztási
maradékot ad.
Párosság vizsgálata: (A % 2 == 0) – a szám kettővel való osztása esetén nincs
maradék.
Elől legyenek a páratlan számok, hátul a párosak: (A % 2 != 0) & (B % 2 == 0).
Két páratlan szám esetén az első kisebb egyenlő legyen, mint a második:
(A % 2 != 0) & (B % 2 != 0) & (A <= B).
Két páros szám esetén az első kisebb egyenlő legyen, mint a második:
(A % 2 == 0) & (B % 2 == 0) & (A <= B).
Tehát a szükséges feltétel:
((A % 2 != 0) & (B % 2 == 0)) | ((A % 2 != 0) & (B % 2 != 0) & (A <= B)) |
((A % 2 == 0) & (B % 2 == 0) & (A <= B)).
Az AND (&) erősebb prioritású művelet, mint az OR ( | ), ezért a külső zárójelek elhagyhatók.
A % szintén erősebb, mint a relációjel, ezért oda nem lett téve zárójel.
Feladat:
Rendezzük az egész számok egy listáját úgy, hogy a páros számok emelkedő, illetve a
páratlan számok csökkenő sorrendben legyenek.
A rendező feladatokban szükséges az elempárok felcserélése. Ennek az algoritmusa a
következő.
Programozási tételek 10 – 11. évfolyam
30. oldal
Algoritmus:
csere(elso, masodik: tipus)
temp: tipus
temp := elso
elso := masodik
masodik := temp
csere vege
A csere eljárás implementálásánál Java nyelven, figyelni kell arra, hogy a Java-ban érték
szerinti paraméterátadás van. (Vagyis referenciát adunk át, például egy tömb nevet, illetve a
két megcserélendő elem indexét.)
A csere referencia átadással (Java):
csere(t: tömb, i: egész, j: egész)
temp: tipus
temp := t[i]
t[i] := t[j]
t[j] := temp
csere vége
A „t” egy tömb referencia, az „i” és „j” a cserélendő elemek indexei.
Minimum-kiválasztásos rendezés
A rendezés egy sorozat elemeinek egymáshoz viszonyított helyét állítja be. A minimum-
kiválasztásos rendezésnél a rendező elv az adott rendezettség szerinti első elem
kiválasztása.
A legegyszerűbb esetben növekvő relációt használunk.
Ebben az esetben a minimum-kiválasztásos rendezés lényege:
Első lépésben megkeressük a sorozat legkisebb elemét. Majd, ha ez nem az első elem,
kicseréljük az első elemmel. Így az első helyen a sorozat legkisebb eleme lesz.
A következő lépésben, a második legkisebb elemet keressük, a még nem rendezett
(második elemtől az utolsóig) részben. A megtalált elemet, ha ez nem egyenlő a
második helyen lévővel, megcseréljük. Ekkor a sorozatunk, a második elemig
rendezett.
A további lépések az előző kettőhöz hasonlóan futnak le, mindig megkeresve a sorozat
következő legkisebb elemét. Amely ez által addig rendezetté válik.
Utolsó lépésként az utolsó előtti helyre kell kiválasztani a legkisebb elemet. Ezt
követően a sorozat rendezetté válik.
Programozási tételek 10 – 11. évfolyam
31. oldal
Algoritmus:
Ciklus i := 1-től a sorozat vége -1-ig
minindex := i
Ciklus j := i + 1-től a sorozat végéig
Ha sorozat[j] < sorozat[minindex] akkor
minindex := j
Ha vége
Ciklus vége
Ha i <> minindex akkor
Csere(sorozat[i], sorozat[minindex])
Ha vége
Ciklus vége
A Csere() eljárás hívása a Java-ban, a következőre módosul az érték szerinti paraméterátadás
miatt: Csere(sorozat, i, minindex). Átadjuk a tömb referenciát, majd a két cserélendő elem
helyét a tömbben. Ezzel a tömb referencia átadással a változás maradandó lesz.
Példa:
3, 6, 2, 7, 4, 9, 1, 8, 5 rendezetlen sorozat
1, 6, 2, 7, 4, 9, 3, 8, 5
1, 2, 6, 7, 4, 9, 3, 8, 5
1, 2, 3, 7, 4, 9, 6, 8, 5
1, 2, 3, 4, 7, 9, 6, 8, 5
1, 2, 3, 4, 5, 9, 6, 8, 7
1, 2, 3, 4, 5, 6, 9, 8, 7
1, 2, 3, 4, 5, 6, 7, 8, 9
1, 2, 3, 4, 5, 6, 7, 8, 9 rendezett sorozat
Ciklusok száma: 8
Feladat:
Generáljunk egy véletlen egész számokat tartalmazó tömböt, és rendezzük növekvő,
sorrendbe.
Java-kód:
package minkivalrendezes;
import java.util.Random;
public class MinKivalRendezes {
public static void main(String[] args) {
Random rnd = new Random();
// 20 elemű tömb deklarálása és feltöltése 0..100
közötti számokkal
int [] t = new int[20];
for(int i = 0; i < t.length; i++)
t[i] = rnd.nextInt(101);
// elemek kiíratása foreach jellegű ciklussal
System.out.println("Rendezetlen sorozat:");
for(int e : t)
System.out.print(e+", ");
System.out.println("");
// elemek rendezése minimum-kiválasztásos rendezéssel
int minIndex;
Programozási tételek 10 – 11. évfolyam
32. oldal
for(int i = 0; i < t.length-1; i++){
// feltételezzük, hogy az i. elem a legkisebb
minIndex = i;
for(int j = i+1; j < t.length; j++){
// ha találtunk a minIndex. elemtől kisebbet
if(t[j] < t[minIndex]){
// akkor megjegyezzük az indexet
minIndex = j;
}
}
// ha a minIndex != i-vel akkor találtunk kisebbet,
és akkor csere
if(minIndex != i){
// cserélje meg a t tömbben az i. elemet a
minIndex. elemmel
csere(t, i, minIndex);
}
}
// rendezés után kiíratjuk
System.out.println("Rendezett sorozat:");
for(int e : t)
System.out.print(e+", ");
System.out.println("");
}
// a csere metódus definiálása, paraméterek a tömb, és a
két index
public static void csere(int[] t, int i, int j){
// segéd változó a cseréhez temporary - ideiglenes
int temp;
temp = t[i];
t[i] = t[j];
t[j] = temp;
}
}
Feladat:
Mit kell megváltoztatni az előző feladatban, hogy csökkenő rendezést kapjunk?
Feladat:
Generáljunk egy egészeket tartalmazó 20 elemű tömböt, majd rendezzük úgy, hogy
elől legyenek a páros számok növekvő, végül a páratlanok csökkenő sorrendben.
Java-kód:
package rendezesparosparatlan;
import java.util.Random;
public class RendezesParosParatlan {
public static void main(String[] args) {
// deklaráció
int[] tomb = new int[20];
// tömb feltöltése véletlen számokkal
feltolt(tomb);
// elemek kiíratása
Programozási tételek 10 – 11. évfolyam
33. oldal
System.out.println("A tömb elemei:");
lista(tomb);
// rendezés
rendez(tomb);
// rendezett tömb kiíratása
System.out.println("\nA rendezett tömb elemei:");
lista(tomb);
}
// a tömb feltöltése véletlen számokkal 0..100
public static void feltolt(int[] t){
Random rnd = new Random();
for(int i = 0; i < t.length; i++)
t[i] = rnd.nextInt(101);
}
// a tömb elemeinek listázása
public static void lista(int[] t){
for(int i = 0; i < t.length; i++)
System.out.print(t[i]+", ");
System.out.println("");
}
// a rendezettség megállapítása függvénnyel
public static boolean rendezett(int a, int b){
// a következő esetekben ad vissza igazat
// ha a, b páros és a < b
// ha a, b páratlan és a > b
// ha a páros és b páratlan
return ((a % 2 == 0) && (b % 2 == 0) && (a < b)) ||
((a % 2 != 0) && (b % 2 != 0) && (a > b)) ||
((a % 2 == 0) && (b % 2 != 0));
}
// a csere eljárás megvalósítása
public static void csere(int[] t, int mit, int mivel){
int temp = t[mit];
t[mit] = t[mivel];
t[mivel] = temp;
}
// a tömb eleminek rendezése minimum-kiválasztásos
rendezéssel
public static void rendez(int[] t){
int minIndex;
for(int i = 0; i < t.length-1; i++){
minIndex = i;
for(int j = i+1; j < t.length; j++){
if(!rendezett(t[minIndex], t[j]))
minIndex = j;
}
if(minIndex != i){
csere(t, i, minIndex);
}
}
}
}
Futási kép:
A tömb elemei:
Programozási tételek 10 – 11. évfolyam
34. oldal
7, 90, 48, 44, 37, 52, 30, 29, 67, 92, 30, 24, 22, 84, 26, 42,
13, 65, 96, 98,
A rendezett tömb elemei:
22, 24, 26, 30, 30, 42, 44, 48, 52, 84, 90, 92, 96, 98, 67, 65,
37, 29, 13, 7,
BUILD SUCCESSFUL (total time: 0 seconds)
Maximum kiválasztásos rendezés
A reláció megfordul, nem a legkisebbet, hanem a legnagyobbat keressük.
Gyakorlás
Feladat:
Rendezzük az előző sorozatot úgy, hogy a páros számok növekvő, majd a páratlanok
csökkenő sorrendben legyenek.
Java-kód:
Elég az előző feladat rendezettséget megállapító függvényét aktualizálni.
// a rendezettség megállapítása függvénnyel
public static boolean rendezett(int a, int b){
// a következő esetekben ad vissza igazat
// ha a, b páros és a < b
// ha a, b páratlan és a > b
// ha a páros és b páratlan
// ha a páratlan és b páros
return ((a % 2 == 0) && (b % 2 == 0) && (a < b)) ||
((a % 2 != 0) && (b % 2 != 0) && (a > b)) ||
((a % 2 == 0) && (b % 2 != 0)) ||
((a % 2 != 0) && (b % 2 == 0));
}
Futási kép:
A tömb elemei:
10, 37, 35, 7, 100, 40, 9, 36, 38, 72, 94, 96, 7, 2, 11, 92,
63, 19, 84, 57,
A rendezett tömb elemei:
2, 63, 57, 37, 10, 36, 35, 38, 40, 72, 84, 92, 19, 94, 11, 96,
9, 7, 100, 7,
BUILD SUCCESSFUL (total time: 0 seconds)
A következő feladatban a rendezendő elemek nem primitív típusok, hanem objektumok. Így
reláció jelekkel közvetlenül nem tudjuk az elsőbbséget megállapítani. Objektumok
összehasonlítására a compareTo() metódus használható. A String osztály tartalmazza, nekünk
csak használnunk kell. Az általunk létrehozott osztályokban többnyire a programozónak kell
megvalósítani.
Programozási tételek 10 – 11. évfolyam
35. oldal
Feladat:
Rendezzünk egy sztringeket tartalmazó 10 elemű tömböt nagyság szerint.
Java-kód:
package rendezesstring;
import java.util.Scanner;
public class RendezesString {
public static void main(String[] args) {
// deklaráció
String[] tomb = new String[10];
// tömb feltöltése sztringekkel
feltolt(tomb);
// elemek kiíratása
System.out.println("A tömb elemei:");
lista(tomb);
// rendezés
rendez(tomb);
// rendezett tömb kiíratása
System.out.println("\nA rendezett tömb elemei:");
lista(tomb);
}
// a tömb feltöltése sztringekkel
public static void feltolt(String[] t){
Scanner be = new Scanner(System.in);
for(int i = 0; i < t.length; i++){
System.out.print("Szöveg: ");
t[i] = be.nextLine();
}
}
// a tömb elemeinek listázása
public static void lista(String[] t){
for(int i = 0; i < t.length; i++)
System.out.print(t[i]+", ");
System.out.println("");
}
// a rendezettség megállapítása függvénnyel
public static boolean rendezett(String str1, String str2){
// a következő esetben ad vissza igazat
// ha str1 <= str2
return str1.compareTo(str2) <= 0;
}
// a csere eljárás megvalósítása
public static void csere(String[] t, int mit, int mivel){
String temp = t[mit];
t[mit] = t[mivel];
t[mivel] = temp;
}
// a tömb elemeinek rendezése minimum-kiválasztásos
rendezéssel
public static void rendez(String[] t){
int minIndex;
for(int i = 0; i < t.length-1; i++){
minIndex = i;
for(int j = i+1; j < t.length; j++){
Programozási tételek 10 – 11. évfolyam
36. oldal
if(!rendezett(t[minIndex], t[j]))
minIndex = j;
}
if(minIndex != i){
csere(t, i, minIndex);
}
}
}
}
Futási kép:
Szöveg: alma
Szöveg: körte
Szöveg: banán
Szöveg: eper
Szöveg: málna
Szöveg: szamóca
Szöveg: ribizli
Szöveg: szőlő
Szöveg: cseresznye
Szöveg: meggy
A tömb elemei:
alma, körte, banán, eper, málna, szamóca, ribizli, szőlő,
cseresznye, meggy,
A rendezett tömb elemei:
alma, banán, cseresznye, eper, körte, meggy, málna, ribizli,
szamóca, szőlő,
BUILD SUCCESSFUL (total time: 1 minute 2 seconds)
Feladat:
Töltsünk fel egy 10 elemű tömböt téglalapokkal (osztály létrehozása). Majd rendezzük
terület szerint csökkenő sorrendbe.
Java-kód:
A RendezTeglalapMinKival osztály forráskódja package rendezteglalapminkival;
import java.util.Random;
public class RendezTeglalapMinKival {
public static void main(String[] args) {
// deklarációk
Random rnd = new Random();
Teglalap[] tomb = new Teglalap[10];
int a;
int b;
// tömb feltöltése ciklusban véletlenszám generálással
// 1..100 közötti oldal hosszúságok
for(int i = 0; i < tomb.length; i++){
a = rnd.nextInt(100)+1;
b = rnd.nextInt(100)+1;
// téglalap létrehozása konstruktorral
tomb[i] = new Teglalap(a, b);
}
Programozási tételek 10 – 11. évfolyam
37. oldal
// listázás
System.out.println("Rendezés előtt:");
lista(tomb);
// rendezés terület szerint növekvően
rendez(tomb);
// rendezés után listázás
System.out.println("\nRendezés után:");
lista(tomb);
}
// a téglalapok adatainak listázása
public static void lista(Teglalap[] t){
for(int i = 0; i < t.length; i++)
System.out.println((i+1)+". "+t[i].toString());
}
// minimum-kiválasztásos rendezés
public static void rendez(Teglalap[] t){
int minIndex;
for(int i = 0; i < t.length-1; i++){
minIndex = i;
for(int j = i+1; j < t.length; j++){
if(!rendezett(t[minIndex], t[j])){
minIndex = j;
}
}
if(minIndex != i){
csere(t, minIndex, i);
}
}
}
// terület alapján a rendezettséget mutató metódus
private static boolean rendezett(Teglalap a, Teglalap b){
return a.terulet() < b.terulet();
}
// csere metódus
private static void csere(Teglalap[] t, int i, int j){
Teglalap temp;
temp = t[i];
t[i] = t[j];
t[j] = temp;
}
}
A rendezés a Teglalap osztály egy primitív típusú tulajdonsága (adattagja) alapján történik,
ezért nem kell compareTo() metódus.
A Teglalap osztaly forraskódja package rendezteglalapminkival;
public class Teglalap {
// példány adattagok
private int a;
private int b;
// statikus adattag - a létrehozott téglalap példányok
száma
private static int db = 0;
// konstruktor
Programozási tételek 10 – 11. évfolyam
38. oldal
public Teglalap(int _a, int _b){
a = _a;
b = _b;
db++;
}
// adatlekérdező (getter) példány metódusok
public int getA() {
return a;
}
public int getB() {
return b;
}
// adatlekérdező statikus metódus
public static int getDb() {
return db;
}
// terület számítás
public int terulet(){
return a *b;
}
// kerület számítás
public int kerulet(){
return 2 * (a + b);
}
// toString() metódus
@Override // az Object osztály felülírt metódusa
public String toString(){
return "téglalap:\n"+
" a = "+a+" cm"+"\n"+
" b = "+b+" cm"+"\n"+
" terület = "+this.terulet()+" cm2"+"\n"+
" kerület = "+this.kerulet()+" cm"+"\n";
}
}
Futási kép részlet:
run:
Rendezés előtt:
1. téglalap:
a = 2 cm
b = 19 cm
terület = 38 cm2
kerület = 42 cm
2. téglalap:
a = 68 cm
b = 81 cm
terület = 5508 cm2
kerület = 298 cm
3. téglalap:
a = 5 cm
b = 32 cm
terület = 160 cm2
kerület = 74 cm
Programozási tételek 10 – 11. évfolyam
39. oldal
4. téglalap:
a = 24 cm
b = 49 cm
terület = 1176 cm2
kerület = 146 cm
…
Téglalap objektumok száma: 10 db
…
Rendezés után:
1. téglalap:
a = 2 cm
b = 19 cm
terület = 38 cm2
kerület = 42 cm
2. téglalap:
a = 53 cm
b = 3 cm
terület = 159 cm2
kerület = 112 cm
3. téglalap:
a = 5 cm
b = 32 cm
terület = 160 cm2
kerület = 74 cm
4. téglalap:
a = 46 cm
b = 11 cm
terület = 506 cm2
kerület = 114 cm
Rendezés compareTo() metódussal:
A rendezéskor objektumokat hasonlítunk össze, nem egy primitív értékű résztulajdonságot.
Java-kód:
package rendezteglalapminkival_compareTo;
import java.util.Random;
public class RendezTeglalapMinKival_compareTo {
public static void main(String[] args) {
// deklarációk
Random rnd = new Random();
Teglalap[] tomb = new Teglalap[10];
int a;
int b;
// tömb feltöltése ciklusban véletlenszám generálással
// 1..100 közötti oldal hosszúságok
for(int i = 0; i < tomb.length; i++){
a = rnd.nextInt(100)+1;
b = rnd.nextInt(100)+1;
// téglalap létrehozása konstruktorral
tomb[i] = new Teglalap(a, b);
}
Programozási tételek 10 – 11. évfolyam
40. oldal
// listázás
System.out.println("Rendezés előtt:");
lista(tomb);
// létrehozott téglalpok száma
System.out.println("Téglalap objektumok száma:
"+Teglalap.getDb()+" db");
// rendezés terület szerint növekvőleg
rendez(tomb);
// rendezés után listázás
System.out.println("\nRendezés után:");
lista(tomb);
}
// a téglalapok adatainak listázása
public static void lista(Teglalap[] t){
for(int i = 0; i < t.length; i++)
System.out.println((i+1)+". "+t[i].toString());
}
// minimum-kiválasztásos rendezés
public static void rendez(Teglalap[] t){
int minIndex;
for(int i = 0; i < t.length-1; i++){
minIndex = i;
for(int j = i+1; j < t.length; j++){
// ha a j. elem kisebb mint a minIndex., akkor
csere
if(t[j].compareTo(t[minIndex]) < 0){
minIndex = j;
}
}
if(minIndex != i){
csere(t, minIndex, i);
}
}
}
// csere metódus
private static void csere(Teglalap[] t, int i, int j){
Teglalap temp;
temp = t[i];
t[i] = t[j];
t[j] = temp;
}
}
package rendezteglalapminkival_compareTo;
public class Teglalap {
// példány adattagok
private int a;
private int b;
// statikus adattag - a létrehozott téglalap példányok
száma
private static int db = 0;
// konstruktor
public Teglalap(int _a, int _b){
a = _a;
b = _b;
Programozási tételek 10 – 11. évfolyam
41. oldal
db++;
}
// adatlekérdező (getter) példány metódusok
public int getA() {
return a;
}
public int getB() {
return b;
}
// adatlekérdező statikus metódus
public static int getDb() {
return db;
}
// terület számítás
public int terulet(){
return a *b;
}
// kerület számítás
public int kerulet(){
return 2 * (a + b);
}
// toString() metódus
@Override
public String toString(){
return "téglalap:\n"+
" a = "+a+" cm"+"\n"+
" b = "+b+" cm"+"\n"+
" terület = "+this.terulet()+" cm2"+"\n"+
" kerület = "+this.kerulet()+" cm"+"\n";
}
/*
* összehasonlításhoz a compareTo() metódus
* ha a megszólított objektum területe kisebb, mint a
* paraméterül kapott objektum területe, akkor a
* visszatérési érték negatív, ha egyenlő a két érték,
* akkor az eredmény nulla, ha nagyobb a paraméter
* értéke, akkor pedig pozitív
*/
public int compareTo(Teglalap t){
return this.terulet() - t.terulet();
}
}
Buborék rendezés
A buborék rendezés a szomszédos elemeket cseréli, ha a sorrend nem megfelelő. Kezdetben
az első két elemet hasonlítjuk össze, és szükség esetén felcseréljük őket. A második lépésben
a 2. és a 3. elemet hasonlítjuk, és ha kell, cseréljük. Ezt így folytatjuk a sorozat végéig. Ekkor
növekvő rendezettséget feltételezve a sorozat végén lesz a legnagyobb elem. A második
ciklusban, már csak az utolsó előtti elemig végezzük a hasonlítást és szükség esetén a cserét.
Ha a második ciklus lefutott, a sorozat utolsó két eleme már a helyén van. A harmadik, és az
Programozási tételek 10 – 11. évfolyam
42. oldal
azt követő ciklusokban egyre kisebb része marad rendezetlenül a sorozatnak. Utolsó ciklus az
első két elemet rendezi.
Algoritmus:
Buborék(T: tömb[1..N] egész)
Deklaráció
i, j: egész
Buborék_kezd
Ciklus i:= N-1-től 1-ig -1-esével
Ciklus j:= 1-től i-ig 1-esével
Ha A[j] > A[j+1] akkor
csere(A[j], A[j+1])
Elágazás vége
Ciklus vége
Ciklus vége
Buborék vége
Példa:
Ez a megvalósítás a legegyszerűbb, viszont egy rendezett tömbön is a (külső ciklus) * (belső
ciklus) számszor fut le, és végzi az összehasonlításokat. Javíthatunk az algoritmuson, ha
Programozási tételek 10 – 11. évfolyam
43. oldal
figyeljük, hogy a belső ciklusban történt-e csere. Ha nem, akkor a következő külső ciklusban
sem fog. Így abba lehet hagyni a rendezést. Ezt mutatja be a következő megvalósítás.
Algoritmus:
Buborék2(T: tömb[1..N] egész)
Deklaráció
i, j: egész
vége: logikai
Buborék2 kezdet
i:= N-1
vége:= HAMIS
Ciklus amíg i >= 1 ÉS NEM vége
vége:= IGAZ
Ciklus j:= 1-től i-ig 1-esével
Ha T[j] > T[j+1] akkor
csere(T[j], T[j+1])
vége:= HAMIS
Ha vége
Ciklus vége
i:= i-1
Ciklus vége
Buborék2 vége
Példa:
Programozási tételek 10 – 11. évfolyam
44. oldal
Ha a belső ciklusban kiderül, hogy a sorozat már rendezett, akkor kilép. Viszont a külső
ciklus csak egyet lép, pedig a rendezettség többet is megengedne. Ezen segíthetünk, ha
megjegyezzük azt a sorszámot, ahol utoljára kellett cserélni. E fölött a sorozat rendezett, így
felesleges újra végigjárni. A harmadik algoritmus ezt mutatja be.
Algoritmus:
Buborék3(T: tömb[1..N] egész)
Deklaráció
i, j: egész
utolsó_csere
Buborék3 kezdet
i:= N-1
Ciklus amíg i >= 1
utolsó_csere:= 0
Ciklus j:= 1-től i-ig 1-esével
Ha T[j] > T[j+1] akkor
csere(T[j], T[j+1])
utolsó_csere:= j
Ha vége
Ciklus vége
i:= utolsó_csere-1
Ciklus vége
Buborék3 vége
Példa:
Programozási tételek 10 – 11. évfolyam
45. oldal
A második és a harmadik buborékrendezés akkor hatékony, ha a sorozat nagy része rendezett.
Feladat:
Készítsünk programot, amely az iskolai sportnap eredményeit tárolja és dolgozza fel!
A sportnapon egyéni számok vannak (futás, gerelyhajítás, kislabdadobás,
kosárbadobás). Vigyük fel az adatokat 5 diákra, és listázzuk ki csökkenő sorrendben
az eredményeket számonként, és összesítésben is. Az összesítésben a sorrendet az
határozza meg, hogy ki nyert többször.
Feladat:
Tároljuk el egy hónap napi középhőmérsékleti értékeit! Majd menüből engedje meg az
adatok módosítását, adjon listát a bevitt adatokról akár nap szerinti sorrendben, akár
hőméréskelt szerint növekvően, vagy csökkenően. A naphoz írjuk ki a hőmérsékletet,
és a hőmérséklethez a napot.
Beszúrásos rendezés
A beszúrásos, vagy pókerrendezés hasonlít arra, ahogy az ember kártyaosztás után elrendezi a
lapokat a kezében. Felvesszük az első lapot, majd a másodikat, és helyére tesszük. A helyét,
egy adott rendező elv határozza meg. Minden újabb lapnál megkeressük és elkészítjük a
helyét, majd betesszük a lapot.
Algoritmus:
Beszúrásos(T: tömb[1..N] egész)
Deklaráció
x, i, j: egész
Beszúrásos kezdet
Ciklus i:= 2-től N-ig
j:= i-1
x:= T[i]
Ciklus amíg j >= 1 ÉS x < T[j]
T[j+1]:= T[j]
j:= j-1
Ciklus vége
T[j+1]:= x
Ciklus vége
Beszúrásos vége
Előnyök:
Hatékony kis adatsorok esetén
Hatékony, ha az adatsorok már részben rendezettek
Gyakorlatban hatékonyabb a többi O(n2)-es rendezésnél
Online algoritmus, képes rendezni egy listát az új elemek felvételekor
Programozási tételek 10 – 11. évfolyam
46. oldal
Rendezések összehasonlítása4
A rendezések hatékonyságát általában a szükséges összehasonlítások, cserék átlagos és
maximális száma és az extra tárigény alapján végezzük.
„A nagy ordó jelölés egy olyan, matematikában használt jelölésmód, amely tömören fejezi ki
egy adott függvény növekedésének mértékét. Informatikában általában egy algoritmus
futásidejének jellemzésére használjuk: a vizsgált függvény a futáshoz szükséges időt adja meg
a bemenet hosszának függvényében. Leegyszerűsítve, egy O(n^2) futásidejű algoritmus kétszer
akkora méretű bemenetre négyszer annyi ideig fog futni, háromszor akkora bemenetre
kilencszer annyi ideig. Míg maga a futásidőt leíró függvény függ az implementáció részleteitől
és a futtatáshoz használt architektúrától, az algoritmus nagy ordója csak az algoritmus
alapelvétől függ.”5
Minimum-kiválasztásos rendezés
Helyfoglalás: N+1, azaz O(N)
Hasonlítások száma: N*(N-1)/2, azaz O(N2)
Mozgatások száma: 3*(N-1)/2, azaz O(N)
Buborék rendezés
Helyfoglalás: N+1, azaz O(N)
Hasonlítások száma: N*(N-1)/2, azaz O(N2)
Mozgatások száma: 0 – 3*N*(N-1)/2, azaz O(N2)
Javított Buborékos rendezés
Helyfoglalás: N+1, azaz O(N)
Hasonlítások száma: N-1 – N*(N-1)/2, azaz O(N2)
Mozgatások száma: 0 – 3*N*(N-1)/2, azaz O(N2)
Beszúró rendezés
Helyfoglalás: N+1, azaz O(N)
Hasonlítások száma: N-1 – N*(N-1)/2, azaz O(N2)
Mozgatások száma: 0 – 3*N*(N-1)/2, azaz O(N2)
4 https://hu.wikipedia.org/wiki/Rendezés_(programozás) 5 http://wiki.prog.hu/wiki/Nagy_ordó_jelölés
Programozási tételek 10 – 11. évfolyam
47. oldal
Gyorsrendezés
Rekurzív algoritmus, kettéosztja a rendezendő listát egy kiemelt elemnél kisebb és nagyobb
elemekre, majd a részekre külön-külön alkalmazza a gyorsrendezést.
Átlagos eset: 𝑂(𝑛 lg 𝑛)
Legrosszabb eset:
Tárigénye:
Kupacrendezés
A kupacrendezés a használt adatszerkezetről kapta a nevét, a kupacról. Működése során
felépíti a kupacot, majd egyesével kiemeli a gyökérelemet, ami a kupac definíciója miatt a
legnagyobb/legkisebb elem lesz.
Átlagos eset:
Legrosszabb eset:
Tárigénye:
Rendezések animációit bemutató oldal: http://tenger.web.elte.hu/flash/index.htm
Halmazműveletek A halmaz a matematika egyik legalapvetőbb fogalma, melyet leginkább az „összesség”,
„sokaság” szavakkal tudunk körülírni, de mivel igazából alapfogalom; így nem tartjuk
definiálandónak. A naiv halmazelméletben egy halmaz meghatározott, egymástól különböző
objektumok gyűjteménye, összessége. Ezeket az objektumokat a halmaz elemeinek
nevezzük. Azt, hogy eleme az halmaznak, így jelöljük: . Azt pedig, hogy nem
eleme, így: 𝑎 ∉ 𝐴
Tulajdonságok:
Legyenek és tetszőleges halmazok. Akkor mondjuk, hogy az és halmazok
egyenlőek, ha ugyanazok az elemeik, és ezt így jelöljük: .
Azt mondjuk, hogy az halmaz részhalmaza a halmaznak (vagy más szavakkal:
a halmaz tartalmazza az halmazt), ha az minden eleme a halmaznak is
Programozási tételek 10 – 11. évfolyam
48. oldal
eleme. Ezt így jelöljük: . Az halmazt a halmaz valódi részhalmazának
nevezzük, ha , és . A valódi részhalmaz jele: 𝐴 ⊂ 𝐵
Azt a halmazt, amelynek minden elemére teljesül, hogy és/vagy , az
és halmazok egyesítésének (más szóval uniójának) nevezzük, és így jelöljük:
.
Azt a halmazt, amelynek minden elemére teljesül, hogy és is, az
és halmazok metszetének nevezzük, és így jelöljük: .
Azt a halmazt, amelynek minden elemére teljesül, hogy , de , az
és halmazok különbségének nevezzük, és így jelöljük: .6
6 Forrás: http://hu.wikipedia.org/wiki/Halmaz
Programozási tételek 10 – 11. évfolyam
49. oldal
Metszetképzés tétele
A programozási feladatoknál a halmazokat többnyire tömb adatszerkezettel ábrázoljuk
(reprezentáljuk), így elemek sorozataival dolgozunk.
A metszet, vagy közös rész meghatározása során két vagy több sorozat azon elemeit
válogatjuk ki, amelyek minden sorozatban benne vannak. A sorozatok nincsenek rendezve, és
feltételezzük, hogy minden elem csak egyszer fordul elő az egyes sorozatokban. A képződő
sorozat elemszáma kisebb vagy egyenlő, mint a legkisebb elemszámú bemenő sorozat
elemszáma.
A feladatot úgy oldjuk meg, hogy végigmegyünk az egyik sorozaton, és az aktuális elemet
keressük a többi sorozatban. Ha mindegyikben benne van, akkor betesszük a közös rész
sorozatába.
Pl. adott két halmaz:
A = {4, 7, 3, 9, 0, 8} és elemszám: 6
B = {1, 5, 4, 3, 0, 2, 6, 9} halmazok közös része elemszám: 8
𝐴 ∩ 𝐵 = {4, 3, 9, 0} elemszám: 4.
Algoritmus:
//H1 és H2 halmazok, K azok közös része,
//N, M N természetes számok halmazának, beleértve a 0-át
//feltételezzük, hogy N <= M
Metszet(H1: tömb[N], H2: tömb[M], K: tömb[N])
Deklaráció:
i, j: egész
Metszet kezdet
//A közös rész (K) indexváltozójának inicializálása.
j:=0
//A H1 sorozaton megyünk végig egyesével. - eleme
Ciklus i := 1-től N-ig
Ha H1[i] H2-nek, akkor j := j+1
K[j] := H1[i]
Ha vége
Ciklus vége
Metszet vége
A „H1[i] H2-nek” tartalmazás vizsgálatot érdemes egy külön alprogramban megvalósítani.
Az alprogram függvényszerűen hívódik, és logikai igaz/hamis értéket ad vissza attól függően,
hogy a keresett elem benne van-e a sorozatban.
Programozási tételek 10 – 11. évfolyam
50. oldal
Algoritmus:
Eleme(elem: típus, sorozat: tömb[N]): logikai
Deklaráció:
i : egész
Eleme kezdet
//Végigmegyünk a sorozaton
Ciklus i := 1-től N-ig
Ha elem = sorozat[i], akkor
//Ha megtaláltuk, akkor igazzal térünk vissza.
return true
Ciklus vége
//Ha végigmentünk a sorozaton, akkor nincs benne.
Ha i > N, akkor
return false
Eleme vége
Vizsgáljuk meg azt az esetet, amikor három bemenő sorozatunk van.
Ekkor is végigmegyünk az egyik sorozaton, és sorban megvizsgáljuk az aktuális elemet, hogy
benne van-e a másik két sorozatban. A tartalmazás vizsgálatot szintén alprogrammal
valósítjuk meg, egy összetett feltételben.
Algoritmus:
Metszet(H1: tömb[N], H2: tömb[M], H3: tömb[L], K: tömb[N])
Deklaráció:
i, j: egész
Metszet kezdet
//A közös rész (K) indexváltozójának inicializálása.
j:=0
//A H1 sorozaton megyünk végig egyesével. - eleme
Ciklus i := 1-től N-ig
Ha H1[i] H2-nek és H1[i] H3-nak akkor j := j+1
K[j] := H1[i]
Ha vége
Ciklus vége
Metszet vége
Feladat:
Határozzuk meg két 20 elemű egészeket tartalmazó sorozat közös elemeit! A
sorozatok elemeit véletlen generátorral adjuk meg, ahol az egyes elemek 1..99 közül
kerülhetnek ki.
Java-kód:
package metszet;
import java.util.Random;
public class Metszet {
public static void main(String[] args) {
// sorozatok (halmazok) deklarációi
int[] h1 = new int[20];
int[] h2 = new int[30];
Programozási tételek 10 – 11. évfolyam
51. oldal
int[] kozos = new int[20];
// tömbök feltöltése véletlen elemekkel 1..99
feltolt(h1);
feltolt(h2);
// elemek listázása
System.out.println("Első sorozat elemei:");
lista(h1);
System.out.println("Második sorozat elemei:");
lista(h2);
// közös rész meghatározása
kozosResz(kozos, h1, h2);
// a metszet elemeinek listázása
System.out.println("A közös elemek:");
lista(kozos);
}
// a feltöltést végző metódus,
// minden elem csak egyszer fordul elő
public static void feltolt(int[] t){
Random rnd = new Random();
int vel;
for(int i = 0; i < t.length; i++){
do{
vel = rnd.nextInt(99)+1;
}while(benneVan(t, vel));
// ha előállítottunk egy olyat ami nics benne
t[i] = vel;
}
}
// elemet keresünk egy sorozatban
public static boolean benneVan(int[] t, int v){
int i = 0;
// a feltételek sorrendje nem mindegy
while((i < t.length) && (t[i] != v))
i++;
// az index értékétől függ, hogy megtaláltuk-e
return i < t.length;
}
// a listázást végző metódus
public static void lista(int[] t){
for(int i = 0; i < t.length; i++)
System.out.print(t[i]+", ");
System.out.println("");
}
// a metszetet meghatározó metódus
public static void kozosResz(int[] k, int[] t1, int[] t2){
int kIndex = -1;
// a rövidebb sorozaton végigmegyünk
for(int i = 0; i < t1.length; i++){
// megnézzük, hogy benne van-e
// az adott elem a másik sorozazban
// ha benn van beletesszük a közösbe
if(benneVan(t2, t1[i])){
kIndex++;
k[kIndex] = t1[i];
}
}
Programozási tételek 10 – 11. évfolyam
52. oldal
}
}
Futási kép:
run:
Első sorozat elemei:
72, 45, 69, 14, 63, 96, 51, 56, 64, 36, 29, 59, 89, 71, 90, 82,
93, 37, 11, 98,
Második sorozat elemei:
5, 69, 34, 85, 3, 88, 90, 27, 4, 41, 82, 39, 63, 71, 91, 67, 6,
22, 15, 57, 58, 24, 66, 76, 40, 61, 38, 89, 42, 86,
A közös elemek:
69, 63, 89, 71, 90, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
BUILD SUCCESSFUL (total time: 0 seconds)
A megvalósítás szépséghibája, hogy a közös sorozat elemeit a tömb teljes hosszáig kiírja. Egy
megoldás lehet, ha a listázást a kozosResz() metóduson belül végezzük.
Feladat:
Készítsük el a fenti feladatot három bemeneti sorozatra.
Unióképzés tétele
A bemenő sorozatokból készítünk egy kimenő sorozatot. Itt a bemenő sorozatok egyesítését
(unióját) keressük. Az unióba bekerül az elem, ha része valamelyik kiindulási sorozatnak. A
unió elemszáma maximálisan a kiindulási sorozatok elemszámainak az összege lehet. Itt is
követelmény, hogy az egyes sorozatokban minden elem csak egyszer szerepel.
A feladatot úgy oldjuk meg, hogy az első sorozatot teljes egészében beletesszük a kimenő
sorozatba. Majd a többi sorozatot megvizsgáljuk, hogy van-e olyan elemük, amely még nincs
benne az unió sorozatában és, ha van, akkor beletesszük.
Algoritmus:
//H1 és H2 halmazok, elemszámuk N, M N
//U azok egyesítése, elemszáma L = N+M
Unio(H1: tömb[N], H2: tömb[M], U: tömb[L])
Deklaráció:
i, j: egész
Unio kezdet
//Első sorozat átmásolása a kimenő (U) sorozatba.
//i értékére szükségünk van
i := 0
Ciklus, amíg i <= N
i := i + 1
U[i] := H1[i]
Ciklus vége
//U feltöltése H2-es sorozat azon elemeivel,
//amelyeket még nem tartalmaz.
Programozási tételek 10 – 11. évfolyam
53. oldal
//A ciklus a H2 elemein megy végig.
Ciklus j := 1-től M-ig
//Ha az aktuális elem nincs benne, akkor beletesszük.
Ha H2[j] U-nak, akkor //Az U sorozat indexének (i) értékét léptetni kell.
i := i+1
U[i] := H2[j]
Ha vége
Ciklus vége
Metszet vége
Az elemvizsgálat algoritmusa a metszetképzés tételénél található.
Feladat:
Az előző feladatot bővítve, készítsük el a két sorozat unióját.
Java-kód:
package metszetUnio;
import java.util.Random;
public class MetszetUnio {
public static void main(String[] args) {
// sorozatok (halmazok) deklarációi
int[] h1 = new int[20];
int[] h2 = new int[30];
int[] kozos = new int[20];
int[] unio = new int[20+30];
// tömbök feltöltése véletlen elemekkel 1..99
feltolt(h1);
feltolt(h2);
// elemek listázása
System.out.println("Első sorozat elemei:");
lista(h1);
System.out.println("Második sorozat elemei:");
lista(h2);
// közös rész meghatározása
kozosResz(kozos, h1, h2);
// a metszet elemeinek listázása
System.out.println("A közös elemek:");
lista(kozos);
// unió meghatározása
unioKepzes(unio, h1, h2);
System.out.println("Az egyesítés elemei:");
lista(unio);
}
// a feltöltést végző metódus,
// minden elem csak egyszer fordul elő
public static void feltolt(int[] t){
Random rnd = new Random();
int vel;
for(int i = 0; i < t.length; i++){
do{
vel = rnd.nextInt(99)+1;
}while(benneVan(t, vel));
// ha előállítottunk egy olyat ami nics benne
Programozási tételek 10 – 11. évfolyam
54. oldal
t[i] = vel;
}
}
// elemet keresünk egy sorozatban
public static boolean benneVan(int[] t, int v){
int i = 0;
// a feltételek sorrendje nem mindegy
while((i < t.length) && (t[i] != v))
i++;
// az index értékétől függ, hogy megtaláltuk-e
return i < t.length;
}
// a listázást végző metódus
public static void lista(int[] t){
for(int i = 0; i < t.length; i++)
System.out.print(t[i]+", ");
System.out.println("");
}
// a metszetet meghatározó metódus
public static void kozosResz(int[] k, int[] t1, int[] t2){
int kIndex = -1;
// a rövidebb sorozaton végigmegyünk
for(int i = 0; i < t1.length; i++){
// megnézzük, hogy benne van-e
// az adott elem a másik sorozazban
// ha benn van beletesszük a közösbe
if(benneVan(t2, t1[i])){
kIndex++;
k[kIndex] = t1[i];
}
}
}
// Az uniót meghatározó metódus
public static void unioKepzes(int[] u, int[] t1, int[] t2){
// az első sorozatot teljes egészében
// beletesszük az unió sorozatába
int i;
for(i = 0; i < t1.length; i++)
u[i] = t1[i];
// az i értéke kilépve a ciklusból egyel nő!!!
// végigmegyünk a második tömbön
for(int j = 0; j < t2.length; j++)
// ha még nincs benne a t1-ben a t2 aktuális eleme
if(!benneVan(t1, t2[j])){
// akkor beletesszük az unióba
u[i] = t2[j];
i++;
}
}
}
Különbség-képzés tétele
Egy A és B halmaz különbségén érjük azt az A\B-vel jelölt halmazt, amelynek elemei A-nak
elmei, de B-nek nem.
Programozási tételek 10 – 11. évfolyam
55. oldal
A feladat megoldása: a kisebbítendő „A” sorozaton végigmegyünk, és ha az aktuális elem
nincs benne a B sorozatban, akkor beletesszük a kimeneti (különbség) sorozatba.
Algoritmus:
//K = H1 \ H2
Különbség(H1: tömb[N], H2: tömb[M], K: tömb[L])
Deklaráció:
i, j: egész
Különbség kezdet
j := 0
Ciklus i := 1-től N-ig
Ha H1[i] H2, akkor j := j + 1
K[j] := H1[i]
Ha vége
Ciklus vége
Különbség vége
A „H1[i] H2” (nem eleme) elemvizsgálat a tagadása a fentebb (unióképzésnél)
megfogalmazott tartalmazás vizsgálatot megvalósító függvénynek.
Feladat:
Az előző feladatokat bővítve, készítsük el a sorozatok különbségét. (első \ második)
Java-kód (program részlet):
…
public static void main(String[] args) {
…
int[] minus = new int[20]; // a méret a kisebbítendő
elemszáma
…
// különbség meghatározása
kulonbsegKepzes(minus, h1, h2);
System.out.println("A különbség képzés elemei:");
lista(minus);
}
…
// h1 - h2 különbség képzése
public static void kulonbsegKepzes(int[] m, int[] h1, int[]
h2){
int j = 0;
for(int i = 0; i < h1.length; i++)
if(!benneVan(h2, h1[i])){
m[j] = h1[i];
j++;
}
}
Programozási tételek 10 – 11. évfolyam
56. oldal
Rekurzió A rekurzió során a feladat megoldásához úgy jutunk el, hogy találunk egy ismételt
egyszerűsítési folyamatot. Ennek a folyamatnak olyannak kell lennie, hogy véges sok
lépésben eljussunk egy olyan állapotba, amelynél a megoldás már magától értetődő. Tehát, a
problémát visszavezetjük egy egyszerűbb problémára, majd ezt az egyszerűsítést addig
végezzük, amíg eljutunk a legegyszerűbb (triviális) esethez. Ezt megoldva, már az eggyel
bonyolultabb eset is megoldható, míg végül eljutunk a teljes probléma megoldásához.
Például az első N természetes szám összegének kiszámítása, visszavezethető az N-1 össze-
gének meghatározására, amelyhez még hozzáadjuk az N értékét.
összeg(N) = összeg(N-1) + N
összeg(N-1) = összeg(N-2) + (N-1)
Ezt az egyszerűsítést addig folytatjuk, amíg N=0 legegyszerűbb esetet meg nem találjuk. Ha
ezt ismerjük, akkor meg tudjuk oldani az N=1 esetet is.
összeg(1) = összeg(0) + 1
Nézzük meg egy példán keresztül, legyen N = 5:
összeg(5) = összeg(4) + 5
összeg(4) = összeg(3) + 4
összeg(3) = összeg(2) + 3
összeg(2) = összeg(1) + 2
összeg(1) = összeg(0) + 1
összeg(0) = 0
Ez a triviális eset, innen fokozatosan megoldhatók a bonyolultabb esetek is.
összeg(1) = 0 +1
összeg(2) = 1+2
összeg(3) = 3 +3
összeg(4) = 6 +4
összeg(5) = 10 +5 = 15
Rekurzív függvények
A rekurzív feladatokat, rekurzív alprogramokkal (eljárás, függvény) oldjuk meg.
Beszélhetünk,
közvetlen rekurzióról, amikor az alprogram saját magát hívja meg, illetve
közvetett rekurzióról, amikor az alprogram, egy másik alprogram által hívódik meg.
Az „A” alprogram hívja „B” alprogramot, és „B” hívja „A”-t.
A rekurzív alprogramban szerepelnie kell:
Programozási tételek 10 – 11. évfolyam
57. oldal
egy egyszerűsítési folyamatnak, amely lépésről-lépésre változik és a triviális esetben
végződik,
egy küszöbfeltételnek, amely leállítja az egyszerűsítést.
Az alprogramok hívása során felépül egy hívási lánc, a triviális eset megtalálásáig. Majd
ezután a lánc utolsó tagja (triviális eset) visszaadja a vezérlést a hívási lánc utolsó előtti
tagjának. Miután megoldotta a saját részproblémáját, az ezt megelőző alprogramra kerül a
vezérlés. A részproblémák megoldása a hívási lánc első eleméig folytatódik, amelynek
végrehajtása során a teljes feladat megoldódik.7
Minden alprogram hívása során a verembe kerülnek a lokális változók, a paraméterek, és a
visszatérési cím. A hívási láncon való visszajutást ez az adatszerkezet segíti. A rekurzió
hátránya, hogy a verem egy véges adatszerkezet, ezért a rekurzió mélysége korlátozott. Illetve
az alprogramok hívása lassítja a feldolgozást. Előnye viszont az átláthatóbb
programszerkezet.
Feladat:
Határozzuk meg 1..20 intervallumból választott 10 véletlen egész szám összegét
rekurzív algoritmussal.
Java-kód:
package rekurzivosszegzes;
import java.util.Random;
public class RekurzivOsszegzes {
public static void main(String[] args) {
Random rnd = new Random();
int szam;
System.out.println("A program megadja 10 véletlenül
választott "
+ "egész szám összegét.");
for(int i = 1; i <= 10; i++){
//véletlen szám előállítása 1..20 között
szam = rnd.nextInt(20)+1;
System.out.print(i+". véletlen szám: "+szam);
//rekurzív összegző függvény eredményének kiíratása
System.out.println(" -- összege:
"+osszegRek(szam));
}
}
//Az összegzést megvalósító rekurzív algoritmus
public static int osszegRek(int n){
if(n == 0)
return 0;
7 Juhász István – Programozási nyelvek 1 – Debreceni Egyetem, egyetemi jegyzet, 2001
Programozási tételek 10 – 11. évfolyam
58. oldal
else
return osszegRek(n - 1) + n;
}
}
A rekurzív összegző függvény az első N természetes szám összegzését végzi. Leállító feltétele
az (n==1) eset, ekkor az eredmény 1, egyébként újra hívja magát egyel kisebb értékkel (N-1.
Így kialakul egy programhívási lánc, amely az N = 1 esetben leáll. Majd ezek után a
függvényhívások fordított sorrendben kiértékelődnek, hozzáadódik az „N.” elem, és végül
előáll az eredmény.
Rekurzív és iteratív forma
Minden rekurzív feladatnak, van iteratív párja.
Feladat:
Számítsuk ki egy adott n nemnegatív egész szám összegét iteratív módon.
Java-kód:
package iterativosszegzes;
import java.util.Random;
public class IterativOsszegzes {
public static void main(String[] args) {
Random rnd = new Random();
int szam;
System.out.println("A program megadja 10 véletlenül
választott "
+ "egész szám összegét.");
for(int i = 1; i <= 10; i++){
//véletlen szám előállítása 1..20 között
szam = rnd.nextInt(20)+1;
System.out.print(i+". véletlen szám: "+szam);
//iteratív összegző függvény eredményének kiíratása
System.out.println(" -- összege:
"+osszegIter(szam));
}
}
//Az összegzést megvalósító iteratív algoritmus
public static int osszegIter(int n){
int szum = 0;
for(int i = 0; i <= n; i++)
szum += i;
return szum;
}
}
Iteratív formánál az összegzést végző metódus ciklust használ.
Programozási tételek 10 – 11. évfolyam
59. oldal
Feladat:
Számítsuk ki egy adott n nemnegatív egész szám faktoriálisát (n!).
Java-kód:
package faktorialis;
import java.util.Scanner;
public class Faktorialis {
public static void main(String[] args) {
Scanner be = new Scanner(System.in);
System.out.println("Faktoriális");
System.out.print("Szám: ");
int szam = be.nextInt();
int n;
//-1 végjelig folytatjuk
while(szam != -1){
if(szam < 0)
System.out.println("Csak nemnegatív számnak van
faktoriálisa!");
else {
n = faktRek(szam);
System.out.println(szam+" faktoriálisa: "+n);
}
System.out.print("Szám: ");
szam = be.nextInt();
}
}
//Faktoriálist számító metódus iteratív alak
public static int fakt(int sz){
int n = 1;
if(sz == 0)
return 1;
else{
while(sz > 0){
n *= sz;
sz--;
}
return n;
}
}
//Faktoriálist számító metódus rekurzív alak
public static int faktRek(int sz){
if(sz == 0)
return 1;
else
return sz * fakt(sz-1);
}
}
Programozási tételek 10 – 11. évfolyam
60. oldal
Gyorsrendezés (QuickSort)
„Osztd meg és uralkodj” elve
A gyorsrendezés (quicksort) az egyik leghatékonyabb rendező algoritmus, amely a rekurzióra
épül. A rendezés alapja, hogy a sorozatot az elemek cserélgetésével két olyan részre osztjuk,
amelynek elemei a sorozat egy kitüntetett eleménél kisebbek, illetve nagyobbak. Majd ezt a
módszert alkalmazva a két részsorozatra, végül 1 elemű részsorozatokat kapunk, amelyek már
önmagukban rendezettek. A kitüntetett elem lehet például a sorozat középső eleme.
Rendezendő:
1. 6, 2, 5, 8, 4, 9, 3
Rendezés:
2. 6, 2, 5, 8, 4, 9, 3 3. 6, 2, 5, 3, 4, 9, 8 4. 4, 2, 5, 3, 6, 8, 9 5. 4, 2, 3, 5, 6 6. 2, 4, 3 7. 2, 3, 4
A rendezett sorozat:
2, 3, 4, 5, 6, 8, 9
A sárgával kiemelt elemek felcserélődnek. Aláhúzással lett jelölve az a kezdeti sorozat,
illetve később a részsorozatok, amelyeken belül történik az elemek felcserélése. Az első
sorban látható a rendezetlen sorozat. A második sorban a kitüntetett (középső) elem a 8-as.
Megvizsgáljuk, hogy tőle balra csak kisebbek vannak-e, illetve jobbra csak nagyobbak. A
nem megfelelő elemeket kicseréljük csere(8, 3). A harmadik sorban a 4, 9 egymáshoz képest
jó helyen van. Ezután, mivel i > j kilépünk a ciklusból. Két részsorozat (6, 2, 5, 3, 4) és (9, 8)
képződik, amelyet az első alapján elkezdünk rendezni. A rendezett számoknál nincs aláhúzás.
A 6. sorban újra két sorozat van (2), és (4, 3), a 2 önmagában rendezett, így csak a (4, 3)
sorozatot kell rendezni. Az utóbbi két számot felcserélve a sorozat rendezetté válik. A
rendezéshez 6 cserére volt szükség.
Algoritmus:
Gyorsrendezés(Cím T: tömb[1..N] egész, alsó, felső: egész)
i, j: egész
középső: egész
Gyorsrendezés kezdet
i:= alsó
j:= felső
középső:= (alsó + felső) DIV 2
Ciklus
Ciklus amíg T[i] < T[középső]
Programozási tételek 10 – 11. évfolyam
61. oldal
i:= i + 1
Ciklus vége
Ciklus amíg T[j] > T[középső]
j:= j – 1
Ciklus vége
Ha i < j akkor
Csere(T[i], T[j])
Ha vége
Ha i <= j akkor
i:= i + 1
j:= j – 1
Ha vége
Ciklus vége Ha i > j
Ha alsó < j akkor
Gyorsrendezés(T, alsó, j)
Ha vége
Ha felső > i akkor
Gyorsrendezés(T, i, felső)
Ha vége
Gyorsrendezés vége
Programozási tételek 10 – 11. évfolyam
62. oldal
Felhasznált és ajánlott irodalom 1. Angster Erzsébet – Objektumorientált tervezés és programozás – Java – 2002, 4KÖR
Bt.
2. http://wiki.vmg.sulinet.hu/doku.php?id=informatika:programozas:tetelek – 2015.02.
3. Nagy Gusztáv – Java programozás – v1.3 – 2007
4. Nagy Zsolt – Középiskolai programozás oktatás Pascal nyelven – 2012, saját jegyzet