Documente Academic
Documente Profesional
Documente Cultură
<tip> * <nume_variabil>;
int *p;
Pointerii sunt date care se memoreaz ntr-o zon special din memoria intern,
numit heap.
n Pascal este definit constanta NIL iar n C/C++ constanta NULL avnd ca
valoare pointerul care nu conine nici o adresa, adic ponterul nul.
Ca operatori specifici privind pointerii amintim:
- operatorul de refereniere (@ n Pascal, respectiv, & n C/C++), astfel c @x n
Pascal, respectiv, &x n C/C++ conine adresa variabilei statice x;
- operatorul de adresare (^ n Pascal, respectiv, * n C/C++), astfel c p^ n Pascal,
respectiv, *p n C/C++ conine valoarea pe care o adreseaz pointerul p.
Iat un exemplu de utilizare a variabilelor dinamice i a operatorilor specifici:
Pascal
C/C++
var x: Integer;
p: ^Integer;
Begin
x:=10;
p:=@x;
WriteLn;
Write('p^ este chiar x: ', p^);
End.
#include <iostream.h>
void main(void)
{
int x=10, *p;
cout<<"\nVar. x e la adr: "<<&x;
cout<<" si are valoarea: "<<x;
cout<<"\nVar. p are val.: "<<p;
p=&x;
cout<<" adresand obiectul: "<<*p;
*p=20;
cout<<"\nSi acum x are val.: "<<x;
}
(<tip*)malloc(<tip>
p= new <tip>;
// <tip> este tipul variabilei spre care indic pointerul p
free(p);
delete p;
- funcia ce verific dac exist spaiu disponibil n HEAP pentru a fi alocat variabilei
pointer p
Pascal
C/C++
maxavail();
Funcia maxavail din Pascal ntoarce dimensiunea celei mai mari zone de memorie
din heap, iar funcia malloc din C/C++ ntoarce un pointer care conine adresa primului
octet al zonei alocate, ns, dac spaiul disponibil este insuficient, funcia ntoarce
valoarea NULL (=0). Exemplu:
Pascal
C/C++
if sizeof(int)<=maxavail() then
p=new()
else
WriteLn(Zona HEAP plina!);
if (malloc(sizeof(int))
p=new int;
else
cout<<Zona HEAP plina!;
baza
vrful
O list definit astfel mai poart numele de list liniar simpl sau list liniar
asimetric, deoarece parcurgerea ei nu se poate face dect ntr-un singur sens, plecnd
de la capul listei spre vrful ei.
Pentru simplificarea expunerii, presupunem n continuare c informaia este o dat
de tip ntreg. n acest caz, implementarea unui nod al listei liniare simple se face astfel:
Pascal
C/C++
type pnod = ^nod;
nod = record
info :Integer;
urm: pnod;
end;
struct nod
{ int inf;
nod *urm;
}
typedef struct nod NOD;
INF
3.
4.
(2)
(3)
1.
2.
INF
INF
noul_nod
(1)
se aloc zona de memorie pentru noul_nod;
se copiaz n urm din noul_nod adresa urm din nodul indicat de p (adic
adresa nodului urmtor lui p, deci se face legtura cu succesorul noului nod);
se memoreaz adresa noul_nod n urm din p (deci legtura predecesorului
noului nod)
se memoreaz informaia n cmpul inf din noul_nod.
Varianta Pascal
Varianta C/C++
new(noul_nod);
noul_nod^.urm:=p^.urm;
p^.urm:=noul_nod;
ReadLn(noul_nod^.inf);
{1}
{2}
{3}
{4}
noul_nod=new NOD;
noul_nod->urm=p->urm;
p->urm=noul_nod;
cin<<noul_nod->inf;
//
//
//
//
1
2
3
4
{1}
{2}
{3}
{4}
{5}
{6}
noul_nod=new NOD;
noul_nod->urm=p->urm;
p->urm=noul_nod;
noul_nod->inf=p->inf;
cin<<p->inf;
p=noul_nod;
//
//
//
//
//
//
1
2
3
4
5
6
tergerea unui element n list, aflat dup un nod indicat de pointerul p se face
astfel:
(2)
INF
INF
p
INF
(1) nod_el
2. se copiaz n urm din nodul indicat de p adresa nodului ce urmeaz dup nodul
ce se va elimina (adic se face legtura cu succesorul nodului ce se va elimina);
3. se elibereaz zona de memorie ocupat de nodul ce se elimin.
Pascal
C
C++
nod_el:=p^.urm;
{1}
p^.urm:=p^.urm^.urm;{2}
dispose(nod_el);
{3}
nod_el=p->urm;
//1
p->urm=p->urm->urm;//2
free(nod_el);
//3
nod_el=p->urm; // 1
p->urm=p->urm>urm;//2
delete nod_el; // 3
Ca i la adugarea unui nou nod n list, i la tergerea unui nod din list sunt
posibile mai multe situaii. Listele create cu santinele elimin verificarea unor cazuri
particulare ca, de exemplu, cel n care dorim s eliminm ultimul nod din list sau cel
n care dorim eliminarea unui nod aflat dup cel indicat de p i pointerul p l indic
chiar pe ultimul (deci, dup el nu mai exist nici un nod care sa poat fi eliminat).
Un caz particular este i eliminarea nodului din capul listei:
Pascal
C
C++
nod_el:=cap;
{1}
cap:=cap^.urm;
{2}
dispose(nod_el); {3}
nod_el=cap;
// 1
cap=cap->urm; // 2
free(nod_el
// 3
nod_el=cap;
// 1
cap=cap->urm; // 2
delete nod_el; // 3
#include <iostream.h>
struct nod
{ int inf;
nod *urm;
};
typedef struct nod NOD;
NOD *cap, *p, *noulnod;
int n, i;
void main()
{
cin>>n;
p=new NOD; cap=p;
cin>>p->inf; p->urm=NULL;
for (i=2;i<=n;i++) {
noulnod=new NOD;
cin>>noulnod->inf;
p->urm=noulnod;
p=noulnod; };
noulnod->urm=NULL;
}
p=cap;
while (p!=NULL)
{
cout<<p->inf<<" "; p=p->urm;
}
adc iniializm pointerul p cu adresa capului listei, dup care, n mod repetat, afim
informaia (sau o prelucrm, n funcie de necesiti) iar prin instruciunea p:=p^urm
n Pascal, respectiv p=p->urm n C/C++, ne poziionm pe urmtoarea nregistrare
pn cnd ajungem la ultimul nod unde urmtoarea adres este NIL n Pacal, respectiv
5
O astfel de list poate fi parcurs n ambele sensuri, deci prezint dou grade de
libertate.
Operaiile specifice listelor dublu nlnuite se bazeaz pe aceeai logic aa cum
am vzut la listele simplu nlnuite, doar c trebuie s inem seama c mai exist i
legtura spre elementul anterior i s dm mare atenie ordinii n care ralizm legturile
pentru a nu pierde informaii.
6
INF
INF
INF
INF
INF
INF
O list circular poate fi asimetric sau simetric dup cum elementele listei sunt
dublete, respectiv triplete, adic conin un pointer sau doi pointeri.
Listele circulare se mai numesc i liste nchise, celelalte purtnd numelre de liste
deschise.
La operaiile specifice listelor circulare trebuie s inem cont, n plus, i de
legturile existente ntre ultimul nod i primul nod.
Atragem atenia asupra greelilor frecvente n utilizarea alocrii dinamice pentru
liste:
- nerespectarea succesiunii corecte a operaiilor;
- prelucrarea (citirea, atribuirea) informaiilor naintea alocrii dinamice;
- stabilirea incorect a legturilor (de exemplu, pentru listele circulare la capete se uit
s se nchid cercul de legturi, iar pentru cele necirculare se uit s se stabileasc
legtura nul);
- n momentul tergerii sau inseriei unui nod nu se actualizeaz corect legturile;
- pierderea poziiei capului listei;
- tergerea unui nod naintea prelurii (memorrii) legturii urmtoare;
- inseria unui nod naintea gsirii nodului anterior.
a. p^.adp=q^.adu b. p^.adu=q^.adu
c. p^.adp=q
Varianta C/C++
a. p->adp==q->adu b. p->adu==q->adu c. p->adp==q
3.
a.
a.
4.
a.
a.
5.
d. p^.adp=q^.adp
d. p->adp==q->adp
a. q^.adr^.adr=p
c. p^.adr^.adr=q
b. p^.adr=q
d. q^.adr=p^.adr^.adr
8
Varianta C/C++
a. q->adr->adr==p
c. p->adr->adr==q
b. p->adr==q
d. q->adr==p->adr->adr
Bacalaureat 2007 (Varianta 3, subiectul I.4)
6. Lntr-o list simplu nlnuit, cu cel puin patru elemente, fiecare element reine
n cmpul urm adresa elementului urmtor din list, iar p memoreaz adresa
celui de-al treilea element din list. Atunci q reine adresa primului element din
list dac i numai dac este satisfcut condiia:
Varianta Pascal
a. p^.urm^.urm=q^.urm
c. q^.urm^.urm^.urm=p^.urm
a.
c.
7.
a.
c.
a.
c.
8.
b. p^.urm^.urm=q
d. q^.urm^.urm=p^.urm
Varianta C/C++
p->urm->urm==q->urm
b. p->urm->urm==q
q->urm->urm->urm==p->urm
d. q->urm->urm==p->urm
Bacalaureat 2007 (Varianta 4, subiectul I.5)
Varianta Pascal
lntr-o list simplu nlnuit, cu cel puin dou elemente, fiecare element reine n
cmpul urm adresa elementului urmtor din list, iar q memoreaz adresa
penultimului element din list. Dac p reine adresa unui element ce urmeaz a fi
adugat la sfritul listei i p^.urm are valoarea nil, stabilii care din urmtoarele
este o operaie corect de adugare:
p^.urm=:q
b. q^.urm=:p
q^.urm^.urm =:p
d. p^.urm^.urm=:q
Varianta C/C++
lntr-o list simplu nlnuit, cu cel puin dou elemente, fiecare element reine n
cmpul urm adresa elementului urmtor din list, iar q memoreaz adresa
penultimului element din list. Dac p reine adresa unui element ce urmeaz a fi
adugat la sfritul listei i p->urm are valoarea NULL, stabilii care din
urmtoarele este o operaie corect de adugare:
p->urm=q
b. q->urm=p
q->urm->urm=p
d. p->urm->urm=q
Bacalaureat 2007 (Varianta 5, subiectul I.7)
lntr-o list simplu nlnuit, cu cel puin trei elemente, fiecare element reine n
cmpul nr un numr ntreg i n cmpul urm adresa urmtorului element din
list. Dac variabila prim reine adresa primului element din list, stabilii care
dintre urmtoarele secvene afieaz suma tuturor numerelor memorate n list
mai puin cele reinute de primul i ultimul element:
Varianta Pascal
a. s:=0; p:=prim;
while (p^.urm<>nil) do begin p:=p.^urm; s:=s+p^.nr end;
write(s)
b. s:=0; p:=prim;
while (p^.urm<>nil) do begin s:=s+p^.nr; p:=p.^urm end;
write(s)
9
c. s:=0; p:=prim^.urm;
while (p^.urm<>nil) do begin s:=s+p^.nr; p:=p.^urm end;
write(s)
d. s:=0; p:=prim;
while (p^.urm<>nil) do begin p:=p^.urm; s:=s+p^.nr end;
write(s-p^.nr)
Varianta C/C++
a. s=0; p=prim;
while (p->urm!=NULL) do { p=p->urm; s=s+p->nr ;}
cout<<s; / printf(%d,s);
b. s=0; p=prim;
while (p->urm!=NULL) do {s=s+p->nr ; p=p->urm;}
cout<<s; / printf(%d,s);
c. s=0; p=prim->urm;
while (p->urm!=NULL) do { s=s+p->nr ; p=p->urm;}
cout<<s; / printf(%d,s);
d. s=0; p=prim;
while (p->urm!=NULL) do { p=p->urm; s=s+p->nr ; }
cout<<s-p->nr; / printf(%d,s-p->nr);
Bacalaureat 2007 (Varianta 8, subiectul I.5)
9. ntr-o list circular simplu nlnuit alocat dinamic cu cel puin un element,
fiecare element reine n cmpul nr un numr ntreg i n cmpul urm adresa
urmtorului element din list. tiind c variabila p reine adresa unui element
din list i variabila t este de acelai tip cu variabila p, stabilii care dintre
urmtoarele secvene afieaz toate valorile memorate n elementel listei, fiecare
valoare fiind afiat exact o dat:
Varianta Pascal
a. t:=p;
b. t:=p;
while (t^ .urm<>p) do begin
repeat
write(t^.nr, ); t:=t^.urm
write(t^.nr, ); t:=t^.urm
end
until (t=p)
c. t:=p;
d. t:=p^.urm;
while (t<>p) do begin
repeat
write(t^.nr, ); t:=t^.urm
write(t^.nr, ); t:=t^.urm
end
until (t=p)
Varianta C/C++
a. t=p;
while(t->urm!=p){
cout<<t->nr<<" "; / printf("%d",t->nr);
t=t->urm; }
b. t=p;
do{
cout<<t->nr<<" "; / printf("%d ",t->nr)
t=t->urm;
}while(t!=p) ;
c. t=p;
10
while(t!=p){
cout<<t->nr<<","; / printf("%d",t->nr);
t=t->urm; }
d. t=p->urm;
do{
cout<<t->nr","; / printf <"%d", t->nr) ;
t=t->urm;
}while{t!=p) ;
Bacalaureat 2007 (Varianta 9, subiectul I.1)
4. 3. 5 Probleme rezolvate
1. ntr-o list liniar simplu nlnuit, alocat dinamic, cu cel puin 4 elemente,
fiecare element reine n cmpul urm adresa elementului urmtor sau NIL (n Pascal),
respectiv NULL (n C/C++) dac nu exist un element urmtor, iar n cmpul info o
valoare ntreag. tiind c variabila p reine adresa primului element din list, nlocuii
punctele de suspensie cu expresiile corespunztoare, astfel nct secvena urmtoare s
calculeze n variabila s suma tuturor valorilor elementelor listei.
Varianta Pascal
Varianta C/C++
s:=.....;
while ..... do
begin
p:=p^.urm;
s:=s+p^.info
end;
write(s);
s=...;
while ( ... )
{
p=p->urm;
s=s+p->info;
}
cout<<s; | printf(%d,s);
Varianta C/C++
s:=p^info;
s=p->info;
while p^urm <> NIL do
while ( p->urm )
begin
{
p:=p^.urm;
p=p->urm;
s:=s+p^.info
s=s+p->info;
end;
}
write(s);
cout<<s; | printf(%d,s);
2. O list liniar simplu nlnuit, alocat dinamic, reine n cmpul info al
fiecrui element cte un numr natural din intervalul [1,10000], iar n cmpul adr,
adresa elementului urmtor din list sau NIL (n Pascal), respectiv NULL (n C/C++),
dac nu exist un element urmtor. Considernd c lista este creat i c adresa
primului element este reinut n variabila prim, s se scrie declarrile de tipuri i date
necesare i secvena de program PASCAL (respectiv C/C++) care afieaz pe ecran
numerele memorate n list, care sunt ptrate perfecte.
Exemplu: pentru lista
Rezolvare. Parcurgem lista element cu element, vom verifica dac elementul curent este ptrat
perfect, n caz afirmativ l vom afia
Varianta PASCAL
Varianta C/C++
type pnod=^nod;
nod=record
info:integer;
adr:pnod;
end;
var prim,q:pnod;
k:integer;
.....
q:=prim;
while(q<>Nil)do
begin
k:=q^.info;
if sqrt(k)=int(sqrt(k))
write(q^.info, );
q:=q^.adr;
end;
struct nod
{int info;
nod * adr;
};
nod * prim, *q;
int k;
...
q=prim;
while(q)
{k= q->info;
if(sqrt(k)==(int) sqrt(k))
cout<<q->info<< ;
q=q->adr;
}
#include <stdio.h>
#include <stdlib.h>
struct nod {int inf;
struct nod* leg;};
struct nod* creare();
void parcurgere(struct nod*);
void parcurgere_inv(struct nod*);
void stergere(struct nod*);
12
c: Char;
function creare:nod;
var inf:Integer;
p:nod;
begin
WriteLn('Informatia: ');
ReadLn(inf);
if sizeof(nod)<=maxavail then
begin
new(p);
p^.inf:=inf;
WriteLn('Continuati
introducerea? (y/n) ');
flush(input); c:=ReadKey;
if c<>'n' then
p^.leg:=creare
else p^.leg:=NIL;
creare:=p
end
else
WriteLn('Depasire heap!')
end;
procedure parcurgere(var p:nod);
begin
if(p<>NIL) then begin
Write(p^.inf,' ');
parcurgere(p^.leg)
end
end;
procedure parcurg_inv(var p: nod);
begin
if (p<>NIL) then
begin
parcurg_inv(p^.leg);
Write(p^.inf, ' ');
end
end;
procedure stergere(var p:nod);
begin
if (p<>NIL) then
begin stergere(p^.leg);
dispose(p); end
end;
Begin
cap:=creare;
WriteLn('Parcurgere cap-coada:');
parcurgere(cap); WriteLn;
WriteLn('Parcurgere inversa:');
parcurg_inv(cap);
stergere(cap);
End.
void main()
{struct nod* cap;
cap=creare();
puts("Parcurgere cap-coada ");
parcurgere(cap);
puts("Parcurgere inversa: ");
parcurgere_inv(cap);
stergere (cap);
}
struct nod *creare()
{int inf;
struct nod *p;
printf("Informatia: ");
scanf("%d",&inf);
p= (struct nod*)
malloc(sizeof(struct nod));
p->inf=inf; fflush(stdin);
printf("Continuati introducerea?
(y/n) ");
if (getchar()=='y')
p->leg=creare();
else p->leg=NULL;
return(p);
}
void parcurgere(struct nod *p)
{ if(p!=NULL) {
printf("%d ", p->inf);
parcurgere(p->leg);}
}
void parcurgere_inv(struct nod *p)
{ if (p!=NULL) {
parcurgere_inv(p->leg);
printf("%d ", p->inf);}
}
void stergere(struct nod *p)
{
if (p!=NULL){ stergere(p->leg);
free(p); }
}
coeficient nenul. Vom defini o funcie canonic care va elimina nodurile redundante
din lista de termeni ai unui polinom prin pstrarea fiecrui grad o singur dat: dac
exist dou noduri cu acelai grad, unul din ele va fi eliminat iar coeficientul celuilalt
va lua valoarea sumei coeficienilor celor doi termeni.
Pentru a calcula suma a dou polinoame este suficient s concatenm listele celor
dou polinoame ntr-o a treia list i s apelm subprogramul canonic pentru aceast
list.
Calculul produsului se va face prin procesarea tuturor perechilor de termeni (unul
din fiecare polinom) astfel:
- fiecare pereche va genera un nod n polinomul rezultat;
- gradul noului nod va fi egal cu suma gradelor nodurilor din pereche;
- coeficientul noului nod va fi egal cu produsul coeficienilor termenilor din pereche.
Dup parcurgerea tuturor perechilor se va apela subprogramul canonic.
Varianta Pascal
Varianta C/C++
Program
Suma_si_produs_polinoame;
Uses Crt;
type nod = ^adr;
adr= record
gr, cf: Integer;
urm: nod;
end;
var cap1,cap2,cap: nod;
i: Integer;
function creare:nod;
var cap,p,q: nod;
c:Char;
begin
new(cap); { aici }
Write; Write('Priumul coef. si
gr: ');
ReadLn(cap^.cf, cap^.gr);
cap^.urm:=NIL;
p:=cap; c:='y';
repeat
WriteLn('Continuati?');
flush(input);c:=ReadKey;
if (c='n') then break;
Write('Urm. coef. si gr: ');
new(q); { aici}
ReadLn(q^.cf, q^.gr);
q^.urm:=NIL;
p^.urm:=q; p:=q;
until False;
creare:=cap;
end;
procedure parcurgere(var p:nod);
var q: nod;
begin
if(p=NIL) then
begin
WriteLn('Lista vida!');
exit
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
typedef struct nod
{
int gr;int cf;
struct nod* urm;
}
NOD;
NOD * cap1,*cap2,*cap;
int i;
void parcurgere(NOD* p);
NOD* creare(void);
NOD* suma (NOD* cap1,NOD*
cap2) ;
NOD* produs(NOD* cap1,NOD*
cap2);
NOD *creare(void)
{ NOD *cap,*p,*q;
cap=(NOD*)malloc(sizeof(NOD));
printf("\nPriumul coef. si
gr: ");
scanf (" %d %d", &cap->cf,
&cap->gr);
cap->urm=NULL;
p=cap;
do { printf("Continuati?" );
if (getch()=='n') break;
printf("\nUrm. coef. si
gr: ");
q=(NOD*)malloc(sizeof(NOD));
scanf("%d %d", &q->cf, &q>gr);
q->urm=NULL;
p->urm=q; p=q;
}
while(1);
14
end;
q:=p;
while q<>NIL do
begin
Write(q^.cf,'x^', q^.gr,'+');
q:=q^.urm;
end;
WriteLn(#8, ' ');
end;
procedure canonic(var cap:nod);
var p,q,r: nod;
begin
p:=cap;
while p<>NIL do
begin
q:=p^.urm;
r:=p;
while q<>NIL do
begin
if (p^.gr=q^.gr) then
begin
p^.cf:=p^.cf+q^.cf;
r^.urm:=q^.urm; r:=q;
dispose(q);
end
else r:=q;
q:=q^.urm
end;
p:=p^.urm
end
end;
function suma(var
cap1,cap2:nod):nod;
var p,q,cap,r:nod;
begin
if(cap1<>NIL) then new(cap);
cap^.cf:=cap1^.cf;
cap^.gr:=cap1^.gr;
cap^.urm:=NIL; r:=cap;
p:=cap1^.urm;
while p<>NIL do
begin
new(q);
q^.cf:=p^.cf
;q^.gr:=p^.gr;q^.urm:=NIL;
r^.urm:=q;r:=q;
p:=p^.urm
end;
p:=cap2;
while p<>NIL do
begin
new(q);
q^.cf:=p^.cf;
q^.gr:=p^.gr;q^.urm:=NIL;
if r<>NIL then r^.urm:=q;
r:=q;
return(cap);
}
void parcurgere(NOD *p)
{ NOD *q;
if(!p){ printf("\nLista
vida!"); return;}
for (q=p;q;q=q->urm)
printf ("\n%2d x^%d+", q>cf, q->gr);
printf ("\b " ) ;
}
void canonic(NOD *cap)
{ NOD *p,*q,*r;
for(p=cap;p;p=p->urm)
for(q=p->urm;q;r=q,q=q->urm)
if (p->gr==q->gr)
{ p->cf+=q->cf;
r->urm=q->urm;free(q);
}
}
NOD* suma (NOD* cap1, NOD* cap2)
{ NOD *p,*q,*cap,*r;
if(cap1)
cap=(NOD*)malloc(sizeof(NOD));
cap->cf=cap1->cf; cap>gr=cap1->gr;
cap->urm=NULL; r=cap;
for (p=cap1->urm;p;p=p->urm)
{ q=(NOD*)malloc(sizeof(NOD));
q->cf=p->cf ;q->gr=p->gr;q>urm=NULL;
r->urm=q;r=q;
}
for (p=cap2;p;p=p->urm)
{ q=(NOD*)malloc
(sizeof(NOD));
q->cf=p->cf; q->gr=p->gr;
q->urm=NULL;
if(r) r->urm=q;r=q;
}
canonic(cap);
return cap;
}
NOD* produs (NOD* cap1, NOD*
cap2)
{ NOD *p,*q,*ult,*r,*cap; int
este_cap=0;
este_cap=0;
for (p=cap1;p;p=p->urm)
for (q=cap2;q;q=q->urm)
{if (!este_cap)
{ este_cap=1;
cap=(NOD*)
malloc(sizeof(NOD));
cap->cf=p->cf*q->cf;
15
p:=p^.urm
end;
canonic(cap);
suma:=cap;
end;
function produs (var
cap1,cap2:nod):nod;
var p,q,ult,r,cap:nod;
este_cap:Boolean;
begin
este_cap:=False;
p:=cap1;
while p<>NIL do
begin
q:=cap2;
while q<>NIL do
begin
if (NOT este_cap) then
begin
este_cap:=True;
new(cap);
cap^.cf:=p^.cf*q^.cf;
cap^.gr:=p^.gr+q^.gr;
cap^.urm:=NIL;ult:=cap;
end
else begin
new(r);
r^.cf:=p^.cf*q^.cf;
r^.gr:=p^.gr+q^.gr;
r^.urm:=NIL;
ult^.urm:=r;ult:=r;
end;
q:=q^.urm
end;
p:=p^.urm
end;
canonic(cap);
produs:=cap
end;
Begin
cap1:=creare;canonic(cap1);
WriteLn('Polinomul 1:');
parcurgere(cap1);
cap2:=creare; canonic(cap2);
WriteLn('Polinomul 2:');
parcurgere(cap2);
cap:=suma(cap1,cap2);
WriteLn('Polinomul suma:');
canonic(cap); parcurgere(cap);
cap:=produs(cap1,cap2);
WriteLn('Poiinomul produs:');
canonic(cap);parcurgere(cap);
End.
cap->gr=p->gr+q->gr;
cap->urm=NULL;ult=cap;
}
else {
r=(NOD*)malloc(sizeof(NOD));
r->cf=p->cf*q->cf;
r->gr=p->gr+q->gr;
r->urm=NULL;
ult->urm=r;ult=r;
}
}
canonic(cap);
return cap;
}
void main()
{ clrscr();
cap1=creare();canonic(cap1);
printf("\nPolinomul 1:" );
parcurgere(cap1);
cap2=creare(); canonic(cap2);
printf("\nPolinomul 2:");
parcurgere(cap2);
cap=suma(cap1,cap2);
printf("\nPolinomul suma:");
canonic(cap); parcurgere(cap);
cap=produs(cap1,cap2);
printf("\nPoiinomul produs:");
canonic(cap);parcurgere(cap);
}
16
Varianta C/C++
Type nod=^adr;
adr=record
inf:Integer;
ant, urm:nod;
end;
var nr:Integer;
cap1, cap2: nod;
procedure creare(nr:Integer;
var cap1, cap2:nod);
var i:Integer;
p:nod;
begin
new(cap1);
Write('Informatia capului: ');
ReadLn(cap1^.inf);
cap1^.urm:=NIL;
cap1^.ant:=NIL;
cap2:=cap1;
for i:=2 to nr do
begin
new(p);
Write('Informatia nr.',i,' :');
ReadLn(p^.inf);
p^.ant:=cap2;cap2^.urm:=p;
p^.urm:=NIL;cap2:=p
end
end;
procedure parc(p:nod;tp:Integer);
begin
if p<>NIL then
if tp=1 then
begin
Write(p^.inf, ' ');
parc(p^.urm, tp)
end
else
begin
Write(p^.inf, ' ') ;
parc(p^.ant, tp)
end
end;
procedure sterg(p:nod);
begin
if p<> NIL then
begin
sterg(p^.urm);
dispose(p)
end
end;
17
#include <stdio.h>
#include <stdlib.h> ,
struct nod {int inf;
struct nod *urm,*ant;
};
void creare(int nf,struct
nod**,struct nod**);
void parc(struct nod*,int tp);
void sterg(struct nod*);
void main()
{int nr;
struct nod * cap1,*cap2;
printf("Numarul de elemente: ");
scanf("%d",&nr);
creare (nr, &cap1, &cap2);
puts("\nParcurgere directa");
parc(cap1,1);
puts("\nParcurgere inversa");
parc(cap2,2);
sterg(cap1);
}
void creare(int nr,struct nod
**cap1,
struct nod **cap2)
{int inf, i;
struct nod *p;
*cap1=(struct nod*)
malloc(sizeof(struct nod));
printf ("Informatia capului: ");
scanf (" %d", &inf);
(*cap1)->inf=inf;
(*cap1)->urm=(*cap1)->ant=NULL;
*cap2=*cap1;
for(i=2;i<=nr;i++)
{p=(struct nod*)
malloc(sizeof(struct nod));
printf("Informatia nr.%d: ",i);
scanf(" %d", &inf);
p->inf=inf;
p->ant=*cap2;
(*cap2)->urm=p;
p->urm=NULL;*cap2=p;
}
}
void parc(struct nod *p,int tp)
{if(p)
if(tp==1)
{printf (" %d ", p->inf);
parc(p->urm, tp);
}
Begin
Write('Numarul de elemente: ');
ReadLn(nr);
creare (nr, cap1, cap2);
WriteLn('Parcurgere directa');
parc(cap1,1); WriteLn;
WriteLn('Parcurgere inversa');
parc(cap2,2);
sterg(cap1)
End.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<iostream.h>
struct nod{int cod;
struct nod *urm;};
typedef nod NOD;
NOD *prim,*ultim,*p;
void intrare()
{int codul;
printf("Intra clientul= ");
scanf("%d",&codul);
if(prim==NULL)
{prim=(NOD*)malloc(sizeof(NOD));
prim->cod=codul;
prim->urm=NULL;
ultim=prim;}
else
{p=(NOD*)malloc(sizeof(NOD));
p->cod=codul;
p->urm=NULL;
ultim->urm=p;
ultim=p;}
}
void iesire()
{if(prim==NULL)
{printf("Nu mai sunt clienti\n");
getch();}
else
{printf("Iese clientul %d \n",
prim->cod);
p=prim;
prim=prim->urm;
free(p);
}getch();
}
void afisare()
18
begin
Write(q^.inf);
q:=q^.urm
end
end;
Begin
clrscr;
varf:=cifre;
scrie_cifre(varf);
ReadLn
End.
{if (prim==NULL)
printf("Nu e nimeni la coada\n");
else
{printf("Clientii de la coada:
\n");
p=prim;
do
{printf("%d \n",p->cod);
p=p->urm;}
while (p!=NULL) ;
} getch();}
void main(void)
{char comanda;
prim=NULL;
do {clrscr ();
printf("Comanda: ");
scanf("%c",&comanda);
switch (comanda)
{case 'i':intrare();break;
case 'e' : iesire();break;
case 'l':afisare();break;}}
while(comanda!='s');
}
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<iostream.h>
struct nod{int cod_loc;
struct nod *urm;};
typedef nod NOD;
NOD *prim,*ultim,*p;
void intrare()
{int codul;
printf("Codul loc care intra=");
scanf("%d",&codul);
if(prim==NULL)
//coada vida, se adauga primul el.
{prim=(NOD*)malloc(sizeof(NOD));
prim->cod_loc=codul;
prim->urm=NULL;
ultim=prim;}
else
{p=(NOD*)malloc(sizeof(NOD));
p->cod_loc=codul;
p->urm=NULL;
ultim->urm=p;
ultim=p;}
}
void iesire()//sterg primul el.
19
end;
end;
procedure iesire;
begin
if prim=NIL then
begin
WriteLn('Nu mai sunt clienti');
ReadLn end
else
begin
Write('Iese clientul ',
prim^.cod);
p:=prim;
prim:=prim^.urm;
dispose(p);
ReadLn
end;
ReadLn
end;
procedure afisare;
begin
if prim=NIL then
WriteLn('Nu e nimeni la coada')
else
begin
Write('Clientii de la coada: ');
p:=prim;
repeat
Write(p^.cod, ' ');
p:=p^.urm
until p=NIL
end;
ReadLn; ReadLn
end;
Begin
prim:=NIL;
repeat
clrscr;
Write('Comanda: ');
Read(comanda);
case comanda of
'i':intrare;
'e':iesire;
'l':afisare
end;
until comanda='s'
End.
{if(prim==NULL)
{printf("Depou gol\n");
getch();}
else
{printf("Iese locom. %d \n",
prim->cod_loc);
p=prim;//salvez adr. primului
prim=prim->urm;
free(p);
}getch();
}
void afisare()
{if (prim==NULL)
printf("Depoul este gol\n");
else
{printf("Locom. din depou: \n");
p=prim;
do
{printf("%d \n",p->cod_loc);
p=p->urm;}
while (p!=NULL) ;
} getch();}
void main(void)
{char comanda;
prim=NULL;
do {clrscr ();
printf("Comanda: ");
scanf("%c",&comanda);
switch (comanda)
{case 'i':intrare();break;
case 'e' : iesire();break;
case 'l':afisare();break;}}
while(comanda!='s');
}
4. 3. 6 Probleme propuse
1. S se scrie un subprogram care s realizeze inversarea legturilor ntr-o list
liniar simplu nlnuit.
Indicaii. Pentru a avea sens inversarea, lista trebuie s aib cel puin dou noduri. Vom
utiliza doi pointeri p i q care rein adresa a cte dou noduri succesive i vom parcurge
lista realiznd inversarea legturilor.
20
alte structuri de date alocate static. Reuniunea a dou liste este alctuit din cheile lor
comune i necomune, luate o singur dat.
9. Scriei un subprogram care, primind ca parametri dou liste liniare simplu
nlnuite de numere ntregi, afieaz intersecia celor do liste, fr a folosi tablouri
sau alte structuri de date alocate static. Intersecia a dou liste este alctuit din cheile
lor comune, luate o singur dat.
10. Scriei un subprogram care, primind ca parametri dou liste liniare simplu
nlnuite de numere ntregi, afieaz diferena celor do liste, fr a folosi tablouri sau
alte structuri de date alocate static. Diferena a dou liste este alctuit din cheile primei
liste care nu se afl i-n a doua list.
11. Scriei un program care s creeze o list liniar dublu nlnuit n care nodurile
conin ca informaie numere ntregi i s realizeze principalele operaii cu aceast list
(adugarea unui nou nod, tergerea unui nod, cutarea unui nod care conine ca
informaie o anumit valoare ntreag, etc.).
12. Scriei un program care s creeze o list liniar simplu nlnuit circular n
care nodurile conin ca informaie numere ntregi i s realizeze principalele operaii cu
aceast list (adugarea unui nou nod, tergerea unui nod, cutarea unui nod care
conine ca informaie o anumit valoare ntreag, etc.).
13. Scriei un program care s creeze o list liniar dublu nlnuit circular n care
nodurile conin ca informaie numere ntregi i s realizeze principalele operaii cu
aceast list (adugarea unui nou nod, tergerea unui nod, cutarea unui nod care
conine ca informaie o anumit valoare ntreag, etc.).
14. Scriei un subprogram care, primind ca parametru o list de numere naturale,
afieaz ptratele perfecte aflate n noduri cu numr de ordin impar (primul, al treilea,
al cincilea, etc.) n lista dat.
Exemplu: pentru lista L=(49,45,172,36,169), se vor afia numerele 49 i 169.
15. Construii o list de numere naturale citite din fiierul "nr.txt" (n care fiecare
nod va conine drept informaie un numr din fiier), apoi scriei un subprogram care
afieaz cheile listei a cror sum a cifrelor este egal cu o valoare dat s. Numerele
sunt scrise n fiier unul sub altul, fiecare pe cte un rnd, i nu se cunoate cte astfel
de numere conine fiierul.
Exemplu: Pentru fiierul ce conine numerele 5, 123, 14, 85, 1121, 16 i s=5, se vor
afia numerele 5,14 i 1121.
16. Se citesc de la tastatur numere ntregi, pn la introducerea valorii 0 (care nu
va face parte din irul citit). S se creeze o list liniar simplu nlnuit care s conin
drept chei numerele prime dintre cele citite. Nu se vor folosi vectori sau alte structuri
de date alocate static.
17. Se citete de la tastatur un cuvnt de lungime maxim 80 de caractere.
Memornd caracterele cuvntului ntr-o list simplu nlnuit (n care fiecare nod va
conine n cmpul de informaie un caracter), s se verifice dac respectivul cuvnt este
palindrom. Reamintim: un cuvnt este palindrom dac, citind caracterele sale n ordine
invesr, de la dreapta la stnga, obinem acelai cuvnt. De exemplu, cuvntul "cojoc"
este palindrom.
18. S se construiasc o list liniar simplu nlnuit cu primele n numere naturale
impare. Numerele se vor memora n ordine cresctoare n cmpurile de informaie ale
nodurilor, cte unul n fiecare nod.
22
- dac numrul pe care-l introducem este mai mic dect cel din primul nod, atunci noul
nod se va aduga la nceputul listei, modificndu-se captul acesteia;
- n caz contrar, parcurgem lista pn la identificarea poziiei pe care ar ocupa-o noul
nod pentru ca lista s rmn sortat cresctor dup care inserm nodul cu numrul citit
i corectm legturile;
- mai exist i posibilitatea ca numrul pe care-l adugm n list s fie mai mare dect
numrul din ultimul nod, situaie n care adugm noul nod la sfritul listei.
27. Se citesc de la tastatur n numere naturale, care se memoreaz ntr-o list
(fiecare nod va conine drept informaie unul din cele n numere). Scriei un program
care, pentru fiecare dintre numerele date, construiete lista divizorilor si mai mari ca 1,
apoi, folosind cele n liste de divizori, determin i afieaz divizorii comuni ai celor n
numere.
Exemplu: pentru n=4 i lista iniial L=(15->60->210->90), se vor construi listele Ll=
(3-->5), L2= (3->4->5), L3= (2->3->5->7) i L4= (3->5->6), iar divizorii comuni
memorai n cele patru liste de divizori sunt 3 i 5.
28. Fiierul "fraza.txt" conine pe un singur rnd o fraz, alctuit din cuvinte, ntre
care apar ca separatori spaiul i virgula, fraza ncheindu-se cu caracterul "punct". S se
creeze o list liniar simplu nlnuita cu cuvintele frazei (cmpul de informaie al
fiecrui nod va fi de tip ir de caractere i va memora un cuvnt al frazei), apoi,
parcurgnd lista, s se afieze cuvntul (cuvintele) de lungime maxim. Nu se vor
folosi vectori sau alte structuri alocate static.
Exemplu: Dac n fiier se gsete fraza "mie mi plac caii, sunt mort dup ei", atunci
lista va fi: ('mie"->"mi"->"plac"->"caii"->"sunt"->"mort"->"dup"->"ei"), iar cuvintele
de lungime maxim ce trebuie afiate sunt: "plac", "caii", "sunt", "mort" i "dup".
29. Se citete de la tastatur un ir de caractere alctuit din cel mult 100 de litere ale
alfabetului latin. irul se citete caracter cu caracter, citirea ncheindu-se prin tastarea
caracterului '#', care nu face parte din el. Folosind o list liniar simplu nlnuit, n
care flecare nod va memora n cmpul su de informaie cte un caracter al irului, s
se afieze cea mai lung secven de litere din ir care, luat individual, constituie un
palindrom. Nu se vor utiliza tipul ir de caractere, vectori, sau alte structuri de date
alocate static.
Exemplu: Pentru irul "vbanacmamxmamt", secvenele ce constituie palindroame sunt:
"ana" i "mamxmam", iar cea mai lung dintre acestea este "mamxmam".
Indicaii. Problema se bazeaz pe un algoritm de determinare a unui subir de lungime
maxim cu o anumit proprietate dintr-un ir dat. Pentru testarea proprietii de
palindrom a unui subir putei folosi algoritmul clasic de extragere a cifrelor.
30. Pentru evidena rezultatelor la Bacalaureat obinute de ctre elevii unei coli se
folosete fiierul "bac.txt" care conine:
- pe primul rnd numrul n de elevi;
- pe fiecare din urmtoarele n rnduri media i apoi numele unui elev, separate printrun spaiu.
Folosind o list liniar simplu nlnuit, se cere:
a) s se afieze numele elevului (elevilor) care au obinut media cea mai mare;
b) s se determine media general a colii.
Indicaii: Din fiier se citete mai nti valoarea lui n. apoi ntr-un ciclu, la fiecare pas:
se citesc numele i media unui elev de pe un rnd al fiierului i se creeaz un nod al
24
listei simplu nlnuite, avnd drept informaii numele i media citite. Pentru
determinarea celei mai mari medii, aplicm algoritmul clasic de maxim n list, dar
pentru c pot fi mai muli elevi cu media maxim determinat parcurgem nc o dat
lista i afim acei elevi a cror medie este egal cu maximul. n sfrit, media general
a colii este media aritmetic a mediilor elevilor din list (suma mediilor mprit la
numrul acestora).
31. Un astrolog dorete s efectueze un studiu statistic privitor la influenele astrelor
asupra persoanelor care locuiesc n oraul su. Pentru aceasta are nevoie de un eantion
de n persoane. El va ntocmi o list care s cuprind, pentru fiecare dintre aceste
persoane, numele, ziua i luna naterii, simulat cu ajutorul unei liste liniare alocat
dinamic. Pornind de la aceast list, astrologul nostru trebuie s poat stabili zodiile n
care s-au nscut persoanele, i apoi s determine cte persoane sunt nscute n fiecare
zodie. In acest scop, el va construi cte o list alocat dinamic pentru fiecare zodie n
parte, coninnd persoanele nscute n acea zodie. Realizai un program care s rezolve
problema astrologului nostru. Pentru ca astrologul s fie pe deplin mulumit, v
propunem s-i oferii un program care s afieze i listele tuturor persoanelor nscute n
fiecare zodie, pe lng numrul acestora. Datele de intrare se citesc din fiierul "pers.
txt", care conine:
- pe primul rnd numrul n al persoanelor din eantion;
- pe fiecare din urmtoarele n rnduri, ziua naterii, luna naterii (n cifre) i numele
unei persoane, n aceast ordine, separate prin spaii.
32. La ora de educaie fizic, profesorul a cerut elevilor unei clase s se alinieze n
ce ordine doresc ei. Fiind un mare iubitor al informaticii, el a observat imediat c n
irul de elevi exist situaii n care un elev de nlime maxim este aezat lng unul de
nlime minim. Scriei un program care afieaz perechile de elevi alturai n ir care
ndeplinesc condiia de mai sus, precum i numrul acestor perechi, apoi rearanjeaz
copiii n ir, astfel nct s se obin un numr maxim de perechi cu proprietatea
respectiv. irul de elevi va fi simulat cu ajutorul unei liste n care fiecare nod va
memora numele i nlimea unui elev, i nu se vor folosi nici un fel de structuri de date
alocate static (tablouri, nregistrri, etc). Numrul de elevi, precum i numele i
nlimile elevilor, se citesc de la tastatur.
Rspunsuri la testele gril:
1. c) 2. c) 3. c) 4. c) 5. c) 6. c) 7. c) 8. d) 9. d)
Bibliografie
1. Emanuela Cerchez, Marinel erban - Programarea n limbajul C/C++ pentru
liceu, Editura Polirom, 2006 (trei volume);
2. Dumitru Fanache Informatic, manual pentru clasa a XI-a, varianta C++,
Editura Gimnasium, 2002;
3. George Daniel Mateescu, Pavel Florin Moraru Informatica pentru liceu i
bacalaureat, materia din clasa a XI-a, Editura Donaris, Sibiu, 2006;
4. Daniela Oprescu, Liana Bejan Ienulescu, Viorica Ptracu Informatic,
manual pentru clasa a XI-a, Editura Niculescu, 2002;
5. Dorian Stoilescu Culegere de C/C++, Editura Radial, Galai, 1998;
6. Dorian Stoilescu - Manual de C/C++ pentru licee, Editura Radial, Galai, 1998;
7. Colectiv autori - Bac 2009: subiecte posibile, Editura Cygnus, 2009;
8. *** - Subiecte bacalaureat 2006, 2007, 2008, 2009.
25