Ce este stiva ?
Stiva (sau “stack” in limba engleza) este o structură de date liniara ce lucreaza cu o colectie de date avand doua operatii principale:
- push(int numar) – adauga numar in stiva
- pop() – sterge ultimul element adaugat in lista (peek() – returneaza valoarea acestui element – deseori functia pop() contine si functia peek() integrata).
Modul in care acesta prelucreaza elementele i-a dat denumirea de LIFO ( Last In First Out= ultimul venit-primul servit ).
Cum functioneaza stiva?
Avand in vedere ca este o structura de date secventiala, operatiile push si pop se intampla numai la capatul structurii (acest “capat” este numit top). Acest detaliu permite stivei sa fie implementata ca o lista simpla inlantuita. De mentionat este faptul ca stiva este o structura de date cu un numar total de elemente flexibil.
Stiva functioneaza pe principiul LIFO, imginati-va de exemplu mai multe farfurii expuse pe raft intr-un IKEA.
In mod normal cand faceti cumparaturile puneti in cos prima farfurie. Pe baza acestui principiu functioneaza si stiva – orice element adaugat în ea va fi pus in varful (capatul / top-ul) stivei, iar atunci când dorim sa accesam o anumita farfurie, incepem sa o parcurgem de la varf către baza (nu invers – le-ai sparge pe toate daca ai face invers).
La ce este folosita stiva?
- Backtracking – in momentul cand vrei sa parcurgi un labirint si te blochezi, pentru a retine pasii ce i-ai facut, ii memorezi intr-o stiva. Daca doresti sa te intorci inapoi un anumit numar de pasi, scoti pe rand coordonatele geografice din stiva.
- Inversarea unui string – Daca doresti sa construiesti imaginea in oglinda a unui string (de exemplu din “mere” sa faci “erem” – vei folosii o stiva). Pe masura ce citesti cuvantul, pui fiecare litera in stiva, iar in momentul cand construiesti cuvantul nou, scoti cate o litera pe rand din stiva.
- Multe alte exemple (evaluarea unei expresii, etc)
Cum implementam stiva?
Inainte de a implementa stiva vom traduce denumirile functiilor in engleza (pentru a te familiariza cu libraria STL).
- push(int numar) – adauga un element in stiva
- pop() – sterge ultimul element din stiva
- peek() – afiseaza ultimul element din stiva
- isEmpty() – verifica daca stiva este goala
Nota: Uneori functia pop() vine “la pachet cu functia peek()”
Există două feluri prin care o putem implementa: fie printr-un array, fie printr-o lista simpla inlantuita. La clasa veti aborda prima metoda, pentru ca listele nu mai intra in programa de Bacalaureat (din cate stiu, poate s-a schimbat intre-timp).
Probabil va intrebati: “de ce trebuie sa implementam noi ceva ce este gata scris in STL?“. Raspunsul este foarte simplu: inveti mult mai bine principiile cu care functioneaza si te forteaza sa intelegi programarea mai bine.
Varianta 1 – Utilizarea unui array (multimi)
#include <iostream> using namespace std; const int LIM = 100; bool isEmpty(int k) { if(k == 0) return true; return false; } void push(int stiva[], int &k, int numar) { k = k + 1; stiva[k] = numar; } int peek(int stiva[], int k) { return stiva[k]; } int pop(int stiva[], int &k) { int rezultat = peek(stiva, k); k = k - 1; return rezultat; } int size(int k) { return k; } int main() { int stiva[LIM], k = 0; push(stiva, k, 2); push(stiva, k, 4); push(stiva, k, 6); push(stiva, k, 7); push(stiva, k, 8); cout << pop(stiva, k); cout << pop(stiva, k); cout << pop(stiva, k); return 0; }
Aceasta varianta incalca una din principiile fundamentale ale stivei. Este restrictionata de un numar maxim de elemente. Stiva este o structura de date flexibila.
Varianta 2 – Utilizarea listelor simpu inlantuite
#include <iostream> using namespace std; struct Nod { int data; Nod* next; }; Nod* newNode(int data) { Nod* nodNou = new Nod(); nodNou -> data = data; nodNou -> next = NULL; return nodNou; } bool isEmpty(Nod* top) { return top == NULL; } void push(Nod* &top, int data) { Nod* nodNou = newNode(data); nodNou -> next = top; top = nodNou; } int pop(Nod* &top) { if(isEmpty(top)) return 0; Nod* tmp = top; top = top -> next; int rezultat = tmp -> data; delete tmp; return rezultat; } int peek(Nod* top) { if(isEmpty(top)) return 0; return top -> data; } int main() { Nod* top = NULL; push(top, 2); push(top, 4); push(top, 6); push(top, 7); push(top, 8); cout << pop(top); cout << pop(top); cout << pop(top); return 0; }
Probleme ce utilizeaza stivele
Pentru a va familiariza cu stivele, puteti sa rezolvati problemele