Documente Academic
Documente Profesional
Documente Cultură
Alocarea Dinamica A Memoriei
Alocarea Dinamica A Memoriei
Alocarea Dinamica A Memoriei
Operatori
1) Adresa unei variabile se obtine cu ajutorul operatorului de referinta & care trebuie sa
preceada numele variabilei:
&nume_variabila;
exemplu: adr1=&numar;
2) Pentru a obtine continutul variabilei a carei adresa este memorata , se utilizeaza operatorul
unar *, numit si operator de dereferentiere, are prioritate 2.
Exemplu:
int a=7, *adr=&a;
cout<<*adr;
//variabila a este initializata cu valoarea 7, iar variabila adr este ini// tializata cu adresa lui a, se afiseaza continutul variabilei a(7),
// pornind de la adresa ei, retinuta de adr.
3) Operatorul . numit operator de selectie, are prioritate 1(maxima).
4) Operatorul de selectie directa ->- acceseaza un camp al unei structuri pornind de la un
pointer catre acea structura.
Exemplu: (*adra).nume
Sau
La tiparire: cout<<adra->nume<< <<adra->prenume;
4) Intre variabilele de tip pointer sunt premise atribuiri doar in cazul in care au acelasi tip de
pointer
Exemplu:
int * adr1,*adr2;
float *adr3;
// initializari
atribuirea: adr1=adr2 corecta
atribuirea: adr3=adr2 nu este corecta
Cum putem atribui cotinutul unei variabile de tip pointer catre tipul x, altei variabile de tip
pointer catre tipul y?
Raspuns: se utilizeaza operatorul de conversie explicita:
Intrucat numele unui masiv p dimensional este pointer catre un masiv p-1 dimensional, pentru
a aloca dinamic un masiv se va utiliza un pointer catre masive p-1 dimensionale (ultimele p-1
dimensiuni).
Aplicatie:
1.Se dau doua matrici. Sa se afiseze suma matricelor. Matricele sunt alocate in Heap.
# include <iostream.h>
Void * Cit_mat (int m, int n)
{ int i, j, (* a)[10]=new int[10][10];
For (i=0; i<m;i++)
For (j=0; j<n; j++) cin>>a[i][j];
Return a;
}
Void tip_mat (int m, int n, int (*a) [10])
{int i, j;
For (i=0; i<m; i++)
{ for (j=0; j<n ; j++) cout <<a[i][j]<< ;
Cout<<endl; }
}
Void * Suma_mat( int m, int n, int (*a)[10], int (*b)[10])
{ int i, j, (*c)[10]=new int[10][10];
for (i=0; i<m; i++)
for (j=0; j<n; j++)
c[i][j]=a[i][j]+b[i][j];
return c;
}
main ( )
{ int m, n, i, j, (*c)[10], (*a)[10], (*b)[10];
cout<<m=; cin>>m;
cout<<n=; cin>>n;
a=(int (*) [10]) Cit-mat(m,n);
b=(int (*) [10]) Cit_mat(m,n);
c=(int (*) [10]) Suma_mat(m,n,a,b);
Tip_mat(m,n,c);
}
Liste liniare
Definitia listelor
Def. O lista liniara este o colectie de n 0 noduri, x1, x2, ,xn aflate intr-o relatie de ordine.
Astfel, x1, este primul nod al listei,, xn este ultimul nod al listei.
Operatiile permise sunt:
- accesul la oricare nod al listei in scopul citirii sau modificarii informatiei continute de
acesta;
- adaugarea unui nod;
- stergerea unui nod;
- schimbarea pozitiei unui nod in cadrul listei.
Un vector poate fi privit ca o lista liniara care este alocata secvential.
1. Liste liniare simplu inlantuite (LLSI)
a) Prezentare generala
Def: O lista liniara simplu inlantuita este o structura de forma
inf1 adr2
inf2 adr3
........
adr1
adr2
infn 0
adrn
unde :
-
adr1
adr2
17
adr2
adr3
29
adrn
Daca se citeste un nod nou ,atunci acesta se adauga intr-o inregistrare aflata la inceputul listei,
in urmatoarele etape:
5
se aloca spatiu pentru noua inregistrare, se completeaza campul numeric, iar adresa
urmatoare este cea din v, deci a primului element al liste.
12
adr2
adr1
34
17
adr3
adr2
29
29
adrn
adr1
adrn+1
Adr2
adr1
34
17
adr2
Adr3
adrn
adr1
adrn+1
#include <iostream.h>
struct Nod
{ int info;
Nod * adr_urm;
};
Nod * v;
Nod * Adaug()
{ Nod* c;
int nr;
cout<<numar=; cin>>nr;
if (nr)
{ c=new(Nod);
c->adr_urm=Adaug( );
c->info=nr;
return c;
}
else return 0;
}
void Tip( Nod* v)
{ Nod* c=v;
while ( c )
{cout<<c->info<<endl;
c=c->adr_urm;
}
}
main ( )
{ v=Adaug( );
Tip(v);
}
Mai jos este prezentat un subprogram recursiv care tipareste informatiile in ordine inversa
fata de modul in care se gasesc in lista:
void Tip_inv( Nod* v)
{ if (v)
{ Tip_inv(v->adr_urm);
cout<<v->info<<endl;
}
}
c) Operatii asupra unei liste liniare
Orice lista va fi retinuta prin doua informatii de adresa: a primului nod (v) si a ultimului
nod ( sf ).Structura unui nod al listei este:
struct Nod
{ int info;
Nod* adr_urm;
};
A.Adaugarea unui nod
Se poate face avand:
1)lista vida v retine 0;
Vrem sa adaugam un nod pe care il alocam zonei Heap, adresa nodului va fi in v, si cum are
un singur nod, adresa primului nod este si adresa ultimului , deci continutul lui v va coincide
cu acela a lui sf.
13
v
sf
2) lista este nevida
Fie lista:
13 adr2
27
adr3
39
v
sf
Se adauga un nod cu informatia 6.Initial se aloca spatiu pentru nod.
13
27
39
V
sf
c
Campul de adresa al ultimului nod, cel care are adresa in sf, va retine adresa nodului nou
creat, dupa care si sf va retine aceeasi valoare.
13
27
39
V
sf
Daca nu am fi utilizat varaibila sf pentru a retine adresa ultimului nod, ar fi fost necesar sa
parcurgem intreaga lista , pornind de la v, pentru a obtine adresa ultimului.
Void Adaugare (Nod*& v, Nod*& sf, int val)
{ Nod* c;
if (v= =0)
{ v=new( Nod);
v->info=val;
v->adr-urm=0;
8
sf=v;
}
else
{ c=new(Nod);
sf->adr_urm=c;
c->info=val;
c->adr_urm=0;
sf=c;
}
}
B. Inserarea unui nod, dupa un altul, de informatie data
Initial se face identificarea nodului dupa care se face adaugarea. Se aloca spatiu pentru noul
nod. Se completeaza adresa si anume adresa nodului care urmeaza dupa nodul ales.
13
27
39
46
sf
5
Campul de adresa al nodului cu informatia 3 va retine adresa nodului nou creat:
13
27
39
46
sf
55
un caz aparte apare atunci cand nodul de informatie val este ultimul in lista. In acest caz sf
retine adresa nodului nou creat pentru ca acesta va fi ultimul.
void Inserare_dupa( Nod* v, Nod*& sf, int val, int val1)
{ Nod* c=v, *d;
while (c->info!=val)
c=c->info=adr_urm;
d=new Nod;
d->info=val1;
d->adr_urm=c->adr_urm;
c->adr_urm=d;
if (d->adr_urm= =0) sf=d;
}
C.Inserarea unui nod , inaintea altui nod, de informatie data
39
39
55
27
..........
v
Variabila v va retine adresa celui de-al doilea nod:
13
55
27
39 0
27
39 0
v
Spatiul ocupat de primul nod va fi eliberat
55
v
Programul este urmatorul:
Void Sterg ( Nod*& v, Nod*& sf, int val)
10
{ Nod* c, *man;
if (v->info= = val)
{ man=v;
v=v->adr_urm;
}
else
{ c=v;
while (c->adr_urm->info!=val)
c=c->adr_urm;
man=c->adr_urm;
c-> adr_urm=man->adr_urm;
if (man= = sf) sf=c;
}
delete man;
}
Urmatorul subprogram ne afiseaza lista liniara:
Void Listare(Nod* v)
{ Nod* c=v;
while ( c )
{ cout<< c->info<<endl;
c=c->adr_urm;
}
cout<<endl;
}
In urma tuturor operatiilor facute putem testa aplicatia:
Nod* v, *sf;
int i;
main( )
{ for (i=1;i<=10;i++)
Adaugare (v, sf, i);
Listare (v);
Inserare_dupa(v, sf, 7, 11);
Inserare_dupa(v, sf, 10, 12);
Inserare_dupa(v, sf, 1, 13);
Listare( v );
Inserare_inainte(v, 13,14);
Inserare_inainte(v, 1,15);
Listare (v);
Sterg(v, sf,15);
Sterg(v, sf,13);
Sterg(v, sf,12);
Listare (v);
}
Aplicatie
Sortarea prin insertie
11
Se citesc de la tastatura n numere naturale. Se cere ca cestea sa fie sortate crescator prin
utilizarea metodei de sortare prin insertie.
Metoda consta in a considera primele k valori sortate , urmand sa inseram valoarea k+1 in
sirul deja sortat. Lista va contine valoarea maxima MaxInt alocata deja in lista, deci vom
porni de la o lista nevida. Alocam spatiu in Heap pentru o valoare , apoi aceasta este
citita.Distingem doua cazuri:
a) valoarea citita este mai mica decat prima valoare a listei. Aceasta inseamna ca ea este cea
mai mica si va fi introdusa prima in lista.
b) valoarea citita nu este cea mai mica din lista, deci ea va trebui introdusa in interiorul listei.
Odata gasita adresa acestei valori, avem nevoie de adresa precedenta (pentru aputea lega in
lista noul nod) vom merge cu doi pointeri, c si c1, unde c1 retine adresa inregistrarii cu
valoarea mai mare decat inregistrarea citita, iar c adresa inregistrarii precedente.
#include <iostream.h>
const MaxInt =32000;
struct Nod
{ int info;
Nod* adr_urm;
};
int n,i;
Nod *v, *adr, *c, *c1;
main( )
{ cout<<n=;
cin>>n;
v=new Nod;
v->info=MaxInt;
v->adr_urm=0;
for (i=1;i<=n;i++)
{ adr=new Nod;
cout<<numar=;
cin>>adr->info;
if (adr->info<=v->info)
// primul din lista
{ adr->adr_urm=v;
v=adr; }
else
// nu e primul din lista
{ c=v;
c1=v->adr_urm;
while (c1->info<adr->info)
{ c=c->adr_urm;
c1=c1->adr_urm;
}
c->adr_urm=adr;
adr->adr_urm=c1; }
}
//tiparesc
c=v;
while (c->info!=MaxInt)
{ cout<<c->info<<endl;
12
c=c->adr_urm;
}
}
13