﻿/* Dinamikus memóriakezelés */

#include <iostream>
using namespace std;

/*
Pointer: memóriacím tárolására
alkalmas változó

    - delkaráció:
        alaptípus* változónév;
    - sajátos operátorok:
            * - dereference
            & - address-of
*/
/*
int main()
{
    int i = 20, j = 30;

    int *p = &i; // p-ben megvan az i címe
    cout << *p << endl; // 20
    *p = 5;
    cout << *p << " " << i << endl; // 5 5

    p = &j; // p változik, a j címe lesz benne
    cout << *p << endl; // 30
    */

    /*
        A new és delete operátorok

        new - lefoglal valamennyi memóriát
              és visszatérít egy pointert
              a megkapott terület elejére

        delete - adott címen kezdődő memória-
                 foglalást felszabadít
    */

    /* Szintaxis - 1. változat */
    /*
    int *p = new int;

    *p = 2;
    (*p)++;
    cout << *p << endl;
    // ....

    delete p;
    */

    /* Szintaxis - 2. változat */
    /*
    int n = 30; // jöhet a bemenetről is

    int *p = new int[n];

    *p = 5; // az első
    *(p+29) = 6; // az utolsó elem
    p[0] = 5;
    p[29] = 6; // ezek is helyesen működnek

    cout << p[29] << endl;

    delete[] p;

    return 0;
}
*/

/* Láncolt adatszerkezetek:
    Egyszeresen láncolt lista

    ---> [24, *]        [36, *]     [5,NULL]
              +---------^    +------^
*/
struct Elem
{
    int adat;
    Elem *next; // a következő eleme a listának
                // vagy NULL, ha nincs következő
                // elem
};

void kiir(Elem *p)
{
    while (p != nullptr) {
        cout << p->adat << endl;
        p = p->next;
    }
}

/*
Beszúrás egyszeresen láncolt listába, adott
elem után

    p címen levő elem után be akarjuk szúrni
    az a adatot
*/
void beszur(Elem *p, int adat)
{
    Elem *uj = new Elem;
    uj->adat = adat;
    uj->next = p->next;

    p->next = uj;
}

/*
Törlés egyszeresen láncolt listából

    p címen elemet akarunk törölni
    (feltéve, hogy ez nem az utolsó)

    - az utána következőből rámásoljuk
    az adatot
*/
void torol(Elem *q)
{
    Elem *torolni = q->next;
    q->adat = torolni->adat;
    q->next = torolni->next;

    delete torolni;
}



int main()
{
    Elem* p1 = new Elem;
    Elem* p2 = new Elem;
    Elem* p3 = new Elem;

    //
    // ---> [24, *]        [36, *]     [5,NULL]
    //           +---------^    +------^

    // p1->adat;  - ugyanaz, mint:  (*p1).adat
    p1->adat = 24;
    p1->next = p2;

    p2->adat = 36;
    p2->next = p3;

    p3->adat = 5;
    p3->next = nullptr; // == 0 == NULL

    kiir(p1);
    cout << "-------------" << endl;

    beszur(p1->next, 100);

    kiir(p1);
    cout << "-------------" << endl;

    torol(p1->next);

    kiir(p1);
    cout << "-------------" << endl;

    return 0;
}

// HF. Írjuk meg a kiír függvény rekurzív változatát!
// HF. Írjuk olyan rekurzív kiír függvényt, ami fordított
//     sorrendben írja ki az elemeket!


/*
    Más változat: kétszeresen láncolt lista
        - minden elem tárol pointert az előző elemre is,
        nem csak a következőre
        - ekkor tudunk visszafelé is lépkedni, de több
        memóriát használunk
*/
