Sunteți pe pagina 1din 4

Structura de tip stiv

Stiva este o list pentru care singurele operaii permise sunt: adugarea unui element n stiv i
eliminarea, consultarea sau modificarea ultimului element introdus n stiv.
Pentru nelegere, ne imaginm o stiv de farfurii. Adugarea sau scoaterea unei farfurii se face cu
uurin, numai din vrful stivei. Dup ce am scos toate farfuriile din stiv spunem c stiva este
vid. Principiul stivei are consecine uriae n programare.
Stivele se pot aloca secvenial (ca vectorii). Fie ST[i] un vector. ST[1], ST[2],...,ST[n] pot reine
numai litere sau cifre. O variabil k indic n permanen vrful stivei, adic ultimul element
introdus.
Exemplu:
A

B
A

In stiva iniial vid se introduce litera A, vrful stivei va fi la nivelul 1 (k=1)

Introducem n stiv litera B, deci k va lua valoarea 2

Scoatem din stiv pe B (A nu poate fi scos deocamdat); k=1

Scoatem din stiv pe A; stiva rmne vid; k=0.


n mod practic, la scoaterea unei variabile din stiv, valoarea variabilei ce indic vrful stivei scade
cu 1, iar atunci cnd scriem ceva n stiv, o eventual valoarea rezidual se pierde.
Pe un anumit nivel se reine de regul o singur informaie (liter sau cifr) ns este posibil s
avem mai multe informaii.
n cazul stivei, alocarea secvenial nu prezint mai dezavantaje, ca n cazul mai general al listelor,
pentru c nu se fac operaii de inserare sau tergere n interiorul stivei ci doar n vrful ei.
Singurul dezavantaj n comparaie cu alocarea dinamic nlnuit este dar de faptul c numrul de
noduri memorate la un moment dat este mai mic depinde de gradul de ocupare al segmentului de
date.
n literatura de specialitate se ntlnete termenul de PUSH pentru operaia de adugare n stiv a
unei nregistrri i de POP pentru extragere.
Orice element al stivei se poate accesa nu doar ultimul introdus, doar c n acest caz nu se respect
principiul stivei.
Exemplul 1: Funcia Manna-Pnueli. Se citete x un numr ntreg. Se cere programul pentru
calcularea funciei

x 1, x 12
F x
F (F (x 2)), x 12
1

Pentru x=15 , F(15)=14


Pentru x=8,
F(8)=F(F(10))=F(F(F(12)))=F(F(11))=F(F(F(13)))=F(F(12))=F(11)=F(F(13))=F(12)=11.
Algoritmul folosete o stiv ST i o variabil k ce indic vrful stivei. Algoritmul se bazeaz pe
considerentele:
-

la o nou autoapelare a funciei F se urc n stiv (k se incrementeaz) i se pune noua


valoare

n situaia n care pentru valoarea aflat pe nivelul k se poate calcula funcia, se coboar n
stiv punndu-se pe acest nivel noua valoare.

Algoritmul se ncheie cnd se ajunge n stiv la nivelul 0.


12

10

10

11

11

12
8

13

13
11

11

12

F=11

Programul:
#include<iostream.h>
#include<conio.h>
int st[100],n,k;
void main()
{
clrscr();
cout<<"n=";
cin>>n;
k=1;
st[1]=n;
while (k>0)
if (st[k]<12)
{
k++;
st[k]=st[k-1]+2;
}
else
{
k--;
if(k>0) st[k]=st[k+1]-1;
}
cout<<"n="<<st[1]-1;
getch();
}

Se poate demonstra c pentru valori mai mici dect 12, funcia ia valoarea 11.
Exemplul 2: Funcia lui Ackermann
Se d funcia de mai jos, definit pe produsul cartezian NxN. Se citesc m i n, s se calculeze
Ack(m,n).
2

n 1, m 0

Ack (m, n) Ack (m 1,1), n 0;


Ack (m 1, Ack (m, n 1))altfel

Pentru m=2, n=1


Ack(2,1)=Ack(1,Ack(2,0))=Ack(1,Ack(1,1))=Ack(1,Ack(0,ack(1,0)))=
Ack(1,Ack(0,Ack(0,1)))=Ack(1,Ack(0,2))= Ack(1,3)= Ack(0, Ack(1,2))=
Ack(0, Ack(0, Ack(1,1)))= Ack(0, Ack(0, Ack(0, Ack(1,0))))=
Ack(0, Ack(0, Ack(0, Ack(0,1))))= Ack(0, Ack(0, Ack(0,2)))=
Ack(a, Ack(0,3))= Ack(0,4)=5
Pentru calculul aceste funcii, folosim o stiv dubl ST. Iniial valorile m i n se rein la nivelul 1.Pe
nivelul k al stivei se rein valorile curente m i n. n funcie de valorile acestora se procedeaz
astfel:
- pentru m i n diferite de 0, este necesar un nou calcul de funcie, caz n care se urc pe stiv
i pentru noul nivel se pun argumentele m i n-1;
- pentru cazul n=0 se rmne la acelai nivel n stiv, punnd n locul lui m valoarea m-1 iar
n locul lui n valoarea 1;
- n situaia n care m=0, funcia se poate calcula, se coboar n stiv i se nlocuiete valoarea
lui m cu m-1, valoarea lui n cu valoarea calculat anterior.
Prezentarea grafic a modului de funcionare a algoritmului pentru Ack(2,1).

21

02
21

20
21

13

11
21

13
12

10
11
21

01
11
21

11
12
13

10
11
12
13

01
11
02
12
12
03
13
13
13
04
Ack(2,1)=5
Funcia lui Ackermann ia valori extrem de mari pentru valori mici ale lui m i n. De exemplu, nu
vei reui s calculai Ack(4,4).
#include<iostream.h>
#include<conio.h>
int st[10000][2];
void main()
{
int m,n,k;
clrscr();
cout<<"m=";
cin>>m;
cout<<"n=";
cin>>n;
k=1;
st[k][0]=m;
st[k][1]=n;
while (k>0)
if (st[k][0]&&st[k][1])
{

k++;
st[k][0]=st[k-1][0];
st[k][1]=st[k-1][1]-1;

}
else
if(!st[k][1])
{
st[k][0]=st[k][0]-1;
st[k][1]=1;
}
else
{
k--;
if(k>0) st[k][0]=st[k][0]-1;
st[k][1]=st[k+1][1]+1;
}
cout<<"Ack("<<m<<","<<n<<")="<<st[1][1]+1;
getch();
}

S-ar putea să vă placă și