Vissza a tananyagokhoz

Alap & Összetett Programozási Tételek

A Neumann János Egyetem mérnökinformatikus és programozói vizsgakövetelményeinek algoritmusai tiszta C++ forráskódokkal és működési animációkkal szemléltetve.

Tételek áttekintése:

I. Alap Programozási Tételek

Egyetlen bemeneti sorozaton végeznek vizsgálatot, és egyetlen kimenetet (összeg, darabszám, logikai igaz/hamis, sorszám/index, vagy szélsőérték) szolgáltatnak.

1. Alap Tétel

Összegzés Tétele

Kiszámítja a sorozat elemeinek összegét.

Egy gyűjtőváltozót (szum) 0-ra állítunk, majd a sorozat minden elemét hozzáadjuk a számláló ciklus futása során. Átlagszámítás esetén ezt az összeget osztjuk az elemek számával.

#include <iostream>
using namespace std;

int osszegzes(int tomb[], int meret) {
    int szum = 0;
    for (int i = 0; i < meret; i++) {
        szum += tomb[i];
    }
    return szum;
}

int main() {
    int szamok[] = {4, 7, 2, 9, 1};
    int n = sizeof(szamok) / sizeof(szamok[0]);
    cout << "Osszeg: " << osszegzes(szamok, n) << endl; // 23
    return 0;
}
Működési animáció & szemléltetés Folyamat
4
+
7
+
2
+
9
+
1
23
szum: 0 ➔ 4 ➔ 11 ➔ 13 ➔ 22 ➔ 23 Minden cikluslépés hozzáadja a soron következő elemet a gyűjtőhöz.
2. Alap Tétel

Megszámolás Tétele

Megmondja, hány olyan elem van a sorozatban, amely egy adott tulajdonságnak megfelel.

Egy számláló változót (db) 0-ra inicializálunk. A ciklusban minden elemet megvizsgálunk a feltétellel (pl. páros-e), és ha a feltétel teljesül, megnöveljük a számlálót eggyel.

#include <iostream>
using namespace std;

int megszamlalas_paros(int tomb[], int meret) {
    int db = 0;
    for (int i = 0; i < meret; i++) {
        if (tomb[i] % 2 == 0) {
            db++;
        }
    }
    return db;
}

int main() {
    int szamok[] = {4, 7, 2, 9, 1, 8};
    int n = sizeof(szamok) / sizeof(szamok[0]);
    cout << "Paros elemek szama: " << megszamlalas_paros(szamok, n) << endl; // 3
    return 0;
}
Működési animáció & szemléltetés Folyamat
4 ✓
7 ✗
2 ✓
9 ✗
1 ✗
8 ✓
db = 3
Csak a feltételnek megfelelő (% 2 == 0) elemeknél ugrik a számláló: 1, 2, 3.
3. Alap Tétel

Eldöntés Tétele

Megvizsgálja, hogy van-e a sorozatban adott tulajdonságú elem (az eredmény igaz vagy hamis).

Ciklussal lépkedünk végig a sorozaton. Amint találunk egy olyan elemet, amely kielégíti a feltételt (pl. negatív szám), azonnal megszakítjuk a ciklust és igaz (true) értékkel térünk vissza. Ha a sorozat végére érünk anélkül, hogy találnánk ilyet, az eredmény hamis (false).

#include <iostream>
using namespace std;

bool van_e_negativ(int tomb[], int meret) {
    for (int i = 0; i < meret; i++) {
        if (tomb[i] < 0) {
            return true; // Megtaláltuk, az eredmény azonnal IGAZ
        }
    }
    return false; // Végigértünk, az eredmény HAMIS
}

int main() {
    int szamok[] = {5, 12, -3, 8, 20};
    int n = sizeof(szamok) / sizeof(szamok[0]);
    cout << (van_e_negativ(szamok, n) ? "Van benne negativ szam (true)" : "Nincs benne (false)") << endl;
    return 0;
}
Működési animáció & szemléltetés Folyamat
5
12
-3 🎯
8
20
return true; (Megáll!)
Amint megtalálta az első negatív számot (-3), a keresés azonnal megszakad, nem vizsgálja a hátralévőket!
4. Alap Tétel

Kiválasztás Tétele

Megadja egy adott tulajdonságú elem sorszámát (indexét), amikor BIZTOSAN tudjuk, hogy az elem szerepel a sorozatban.

Mivel előfeltételünk, hogy a keresett elem garantáltan megtalálható a sorozatban (pl. strázsa módszer vagy garantált azonosító), nem szükséges vizsgálni a tömbhatár túllépését; egy while ciklussal addig lépegetünk, amíg el nem érjük az elemet.

#include <iostream>
#include <string>
using namespace std;

// Előfeltétel: A keresett elem BIZTOSAN benne van a tömbben!
int kivalasztas(string tomb[], string keresett) {
    int i = 0;
    while (tomb[i] != keresett) {
        i++; // Addig lépkedünk, amíg meg nem találjuk
    }
    return i; // Visszaadjuk a biztosan megtalált elem sorszámát (indexét)
}

int main() {
    string hallgatok[] = {"Kovacs", "Nagy", "Toth", "Molnar", "Szabo"};
    // Biztosan tudjuk, hogy "Molnar" a listában van:
    int sorszam = kivalasztas(hallgatok, "Molnar");
    cout << "A 'Molnar' nevu hallgato indexe: " << sorszam << endl; // 3
    return 0;
}
Működési animáció & szemléltetés Folyamat
[0] Kovacs
[1] Nagy
[2] Toth
[3] Molnar 🎯
Megtalált index: 3 Biztos előfordulás: addig léptetjük az i indexet, míg rá nem találunk.
5. Alap Tétel

Keresés (Lineáris Keresés) Tétele

Megmondja, hogy szerepel-e a keresett elem, és ha igen, hol (megadja a sorszámát). Ha nincs benne, azt is jelzi.

Összekapcsolja az eldöntést és a kiválasztást: végigvizsgálja a tömböt a mérethatárig. Ha megtalálja, azonnal visszaadja az elem indexét (>= 0). Ha végigért és az elem nem szerepelt a sorozatban, egy speciális hibajelzéssel (tipikusan -1) jelzi a hiányát.

#include <iostream>
#include <string>
using namespace std;

int linearis_kereses(string tomb[], int meret, string keresett) {
    for (int i = 0; i < meret; i++) {
        if (tomb[i] == keresett) {
            return i; // SZEREPEL a sorozatban: visszaadjuk a sorszámát (indexét)
        }
    }
    return -1; // NEM SZEREPEL a sorozatban: -1-gyel jelezzük
}

int main() {
    string nevek[] = {"Gabor", "Peter", "Anna", "Dora"};
    int n = sizeof(nevek) / sizeof(nevek[0]);
    
    int idx1 = linearis_kereses(nevek, n, "Anna");
    if (idx1 != -1) cout << "Anna szerepel a tombben, indexe: " << idx1 << endl;
    else cout << "Anna nincs a tombben!" << endl;

    int idx2 = linearis_kereses(nevek, n, "Bence");
    if (idx2 != -1) cout << "Bence indexe: " << idx2 << endl;
    else cout << "Bence nincs a sorozatban (eredmeny: " << idx2 << ")!" << endl;

    return 0;
}
Működési animáció & szemléltetés Folyamat
[0] Gabor
[1] Peter
[2] Anna 🎯
[3] Dora
Találat: index = 2 (Ha nem lenne benne: return -1;)
6. Alap Tétel

Maximum- és Minimumkeresés Tétele

Megkeresi egy sorozat legnagyobb vagy legkisebb értékét és annak sorszámát (indexét).

A szélsőérték kezdőértékének a sorozat legelső elemét (tomb[0]) választjuk, a kezdő index pedig 0. Ezután a 2. elemtől (index 1) kezdve végigiterálunk a tömbön: ha a vizsgált elem nagyobb a jelenlegi maximumnál (vagy kisebb a minimumnál), frissítjük az értéket és feljegyezzük az új indexet.

#include <iostream>
using namespace std;

void min_max_kereses(int tomb[], int meret, int &maxErtek, int &maxIdx, int &minErtek, int &minIdx) {
    maxErtek = tomb[0];
    maxIdx = 0;
    minErtek = tomb[0];
    minIdx = 0;

    for (int i = 1; i < meret; i++) {
        if (tomb[i] > maxErtek) {
            maxErtek = tomb[i];
            maxIdx = i;
        }
        if (tomb[i] < minErtek) {
            minErtek = tomb[i];
            minIdx = i;
        }
    }
}

int main() {
    int szamok[] = {12, 45, 8, 92, 17, 3, 76};
    int n = sizeof(szamok) / sizeof(szamok[0]);
    int maxVal, maxIdx, minVal, minIdx;

    min_max_kereses(szamok, n, maxVal, maxIdx, minVal, minIdx);

    cout << "Maximum ertek: " << maxVal << " (index: " << maxIdx << ")" << endl;
    cout << "Minimum ertek: " << minVal << " (index: " << minIdx << ")" << endl;
    return 0;
}
Működési animáció & szemléltetés Folyamat
12
45
8
92 👑
17
3 🔻
76
Max: 92 (idx: 3) Min: 3 (idx: 5)
Elválasztva: Összetett Programozási Tételek

II. Összetett Programozási Tételek

Fő jellemzőjük: Ezek a tételek több adatsorozatot hoznak létre vagy alakítanak át (új tömb vagy vektor létrehozása másolással/transzformációval, szűréssel, halmazműveletekkel, vagy a sorozat elemeinek átrendezésével).

1. Összetett Tétel

Másolás (Transzformáció) Tétele

Egy sorozat elemeit átmásolja egy másik sorozatba úgy, hogy közben mindegyiken elvégez egy műveletet (pl. mindegyiket megszorozza kettővel).

Egy forrástömb elemeit egy céltömbbe (vagy vektorba) visszük át úgy, hogy a másolási lépés közben egy tetszőleges transzformációt (szorzás, formázás, matematikai függvény) hajtunk végre az elemen.

#include <iostream>
#include <vector>
using namespace std;

// Transzformáció: minden elem megduplázása
vector<int> masolas_duplazas(int tomb[], int meret) {
    vector<int> cel(meret);
    for (int i = 0; i < meret; i++) {
        cel[i] = tomb[i] * 2; // Művelet elvégzése másolás közben
    }
    return cel;
}

int main() {
    int eredeti[] = {1, 3, 5, 8, 10};
    int n = sizeof(eredeti) / sizeof(eredeti[0]);
    
    vector<int> masolt = masolas_duplazas(eredeti, n);

    cout << "Atmasolt, megduplazott ertekek: ";
    for (int elem : masolt) {
        cout << elem << " ";
    }
    cout << endl; // 2 6 10 16 20
    return 0;
}
Működési animáció & szemléltetés Transzformáció
Forrás:
1
3
5
8
Transzformáció: minden elem megszorzása 2-vel (elem * 2)
Új cél:
2
6
10
16
2. Összetett Tétel

Kiválogatás (Filterezés) Tétele

Egy sorozatból egy másik sorozatba gyűjti azokat az elemeket, amelyek megfelelnek egy feltételnek.

Végigiterálunk a forrássorozaton, megvizsgáljuk a feltételt (pl. páros-e vagy pozitív-e), és csak azokat az elemeket szúrjuk be az új tömbbe vagy vektorba, amelyekre a feltétel igaznak bizonyul.

#include <iostream>
#include <vector>
using namespace std;

// Filterezés: Csak a páros számok összegyűjtése
vector<int> kivalogatas_parosak(int tomb[], int meret) {
    vector<int> kivalogatott;
    for (int i = 0; i < meret; i++) {
        if (tomb[i] % 2 == 0) {
            kivalogatott.push_back(tomb[i]); // Csak a megfelelőt mentjük
        }
    }
    return kivalogatott;
}

int main() {
    int szamok[] = {11, 24, 7, 8, 15, 42, 3};
    int n = sizeof(szamok) / sizeof(szamok[0]);

    vector<int> parosak = kivalogatas_parosak(szamok, n);

    cout << "Kivalogatott paros szamok: ";
    for (int szam : parosak) {
        cout << szam << " ";
    }
    cout << endl; // 24 8 42
    return 0;
}
Működési animáció & szemléltetés Transzformáció
Forrás:
11
24 ✓
7
8 ✓
15
42 ✓
Szűrt új:
24
8
42
Csak a párosak!
3. Összetett Tétel

Metszet Tétele

Két sorozat közös elemeit gyűjti össze egy új sorozatba.

Az első sorozat minden elemére elvégzünk egy eldöntést a második sorozaton. Ha benne van a másodikban is (és az új gyűjtőben még nem szerepel), akkor hozzáadjuk a metszethez.

#include <iostream>
#include <vector>
using namespace std;

// Segédfüggvény: Benne van-e már a vektorban? (Eldöntés tétel)
bool benne_van(const vector<int>& v, int ertek) {
    for (int elem : v) {
        if (elem == ertek) return true;
    }
    return false;
}

vector<int> metszet(int A[], int nA, int B[], int nB) {
    vector<int> kozos;
    for (int i = 0; i < nA; i++) {
        // Megnézzük, hogy A[i] szerepel-e B tömbben:
        bool benne_van_B_ben = false;
        for (int j = 0; j < nB; j++) {
            if (A[i] == B[j]) {
                benne_van_B_ben = true;
                break;
            }
        }
        // Ha mindkettőben benne van és még nem mentettük:
        if (benne_van_B_ben && !benne_van(kozos, A[i])) {
            kozos.push_back(A[i]);
        }
    }
    return kozos;
}

int main() {
    int A[] = {1, 2, 4, 7, 9, 12};
    int B[] = {2, 5, 7, 12, 15};
    int nA = sizeof(A) / sizeof(A[0]);
    int nB = sizeof(B) / sizeof(B[0]);

    vector<int> res = metszet(A, nA, B, nB);

    cout << "A es B metszete (kozos elemek): ";
    for (int x : res) cout << x << " ";
    cout << endl; // 2 7 12
    return 0;
}
Működési animáció & szemléltetés Transzformáció
A halmaz:
1
2
4
7
9
12
B halmaz:
2
5
7
12
15
Metszet:
2
7
12
Közös elemek
4. Összetett Tétel

Unió Tétele

Két sorozat összes elemét egyesíti úgy, hogy a duplikációkat kiszűri.

Első lépésként az első tömb összes elemét átmásoljuk az unióba (duplikátumok nélkül). Második lépésként a második tömb elemeit csak akkor fűzzük hozzá, ha az unió gyűjtemény még nem tartalmazza őket.

#include <iostream>
#include <vector>
using namespace std;

bool benne_van(const vector<int>& v, int ertek) {
    for (int elem : v) {
        if (elem == ertek) return true;
    }
    return false;
}

vector<int> unio(int A[], int nA, int B[], int nB) {
    vector<int> egyesitett;
    // 1. A tömb elemeinek hozzáadása
    for (int i = 0; i < nA; i++) {
        if (!benne_van(egyesitett, A[i])) {
            egyesitett.push_back(A[i]);
        }
    }
    // 2. B tömb elemeinek hozzáadása (ha még nem szerepelnek)
    for (int j = 0; j < nB; j++) {
        if (!benne_van(egyesitett, B[j])) {
            egyesitett.push_back(B[j]);
        }
    }
    return egyesitett;
}

int main() {
    int A[] = {1, 3, 5, 7};
    int B[] = {3, 4, 7, 8, 9};
    int nA = sizeof(A) / sizeof(A[0]);
    int nB = sizeof(B) / sizeof(B[0]);

    vector<int> res = unio(A, nA, B, nB);

    cout << "A es B unioja: ";
    for (int x : res) cout << x << " ";
    cout << endl; // 1 3 5 7 4 8 9
    return 0;
}
Működési animáció & szemléltetés Transzformáció
A:
1
3
5
7
B:
3 ✗
4
7 ✗
8
9
Unió:
1
3
5
7
4
8
9
Minden elem szerepel, de a közös elemek (3, 7) csak egyszer kerülnek bele!
5. Összetett Tétel

Rendezés Tétele

Növekvő vagy csökkenő sorrendbe rendezi a sorozat elemeit (pl. buborékos rendezés, cserés rendezés).

Az elemek páronkénti összehasonlításával és cseréjével (swap) mozgatja a nagyobb elemeket a sorozat végére. A programozásban a leggyakoribb klasszikus algoritmus az egyszerű cserés és a buborékos rendezés (Bubble Sort).

#include <iostream>
using namespace std;

// Buborékos rendezés (Bubble Sort)
void buborekos_rendezes(int tomb[], int meret) {
    for (int i = 0; i < meret - 1; i++) {
        for (int j = 0; j < meret - i - 1; j++) {
            // Ha a bal oldali nagyobb mint a jobb oldali, megcseréljük:
            if (tomb[j] > tomb[j + 1]) {
                int ideiglenes = tomb[j];
                tomb[j] = tomb[j + 1];
                tomb[j + 1] = ideiglenes;
            }
        }
    }
}

int main() {
    int szamok[] = {64, 34, 25, 12, 22, 11, 90};
    int n = sizeof(szamok) / sizeof(szamok[0]);

    buborekos_rendezes(szamok, n);

    cout << "Rendezett tomb (novekvo): ";
    for (int i = 0; i < n; i++) {
        cout << szamok[i] << " ";
    }
    cout << endl; // 11 12 22 25 34 64 90
    return 0;
}
Működési animáció & szemléltetés Transzformáció
12
64 ⇄
25 ⇄
90
12
25
64
90
Buborékos csere (Swap) Ha tomb[j] > tomb[j+1], megcseréljük őket, így a nagy értékek a sor végére "lebegnek fel".