Documente Academic
Documente Profesional
Documente Cultură
46
11.3 Structuri de date înlănŃuite
O lista dublu inlantuita este tot o lista liniara , avand proprietatea ca
11.3.1 Liste liniare poate fi parcursa in ambele sensuri , deci si spre nodul anterior:
47
nod cu câmpurile cheie şi info neprecizate, dar câmpul următor q^.anterior:=sfarsit;
indicând spre primul nod al listei. {asignarea câmpurilor cheie şi info}
De asemenea uneori e util a se păstra pointerul spre ultimul nod al sfirsit:=q;
listei.
O varianta este a listelor circulare la care dispare noŃiunea de Pentru inserŃia la sfârşitul listei e necesara existenŃa a cel puŃin un
prim, ultim nod. nod, care se creează prin procedura de la paragraful anterior.
a)inserŃia unui nod la începutul listei E simplă pentru că se cunoaşte pointerul spre nodul anterior şi
spre cel următor celui ce se inserează (pointerul spre nodul următor e
Dacă început e variabila pointer ce indica spre primul nod al valoarea câmpului următor al nodului indicat).
listei, iar q o variabila auxiliara de tip pointer, secvenŃa următoare new(q);
realizează inserŃia la începutul listei şi actualizează pointerul început: q^.urmator:=p^.urmator; {legăm nodul de nodul anterior}
new(q); {creează spaŃiu pentru un nou nod} q^anterior:=p;
q^.urmator:=inceput; p^.urmator:=q; {legăm nodul anterior de q}
q^.anterior:=nil; p^.urmator^.anterior:=q
{asignarea câmpurilor cheie şi info}
inceput:=q; d)inserŃia unui nod în faŃa unui nod indicat
SecvenŃa e corectă şi pentru inserŃia într-o listă vidă, caz în care
inceput=nil (nil fiind pointerul vid, care nu se refera la nici o variabilă Printr-un artificiu, se reduce acest caz la cel anterior: se inserează
indicată). un nod după cel indicat, cheia şi informaŃia din nodul indicat fiind
atribuite noului nod inserat şi fiind înlocuite cu valorile nodului ce
trebuia inserat.
b)inserŃia unui nod la sfârşitul listei
Devine mai simplă dacă se păstrează o variabilă sfârşit indicând Tehnici de suprimare
spre ultimul nod al listei:
new(q); {creează spatiu pentru noul nod ultim al listei} a) Suprimarea nodului următor celui indicat de o variabila
sfirsit^.urmator:=q; pointer q se face astfel:
q^.urmator:=nil;
48
begin
p:=q^.urmator; {punem un indicator către nodul care urmează a fi write(q^.inf);
şters} q:=q^.urm;
p^.urmator^.anerior:= q; end;
q^.urmator:=p^.urmator;{nodul anterior celui ce urmează a fi şters end.
pointează către nodul următor acestuia}
dispose(p);{ eliberăm memoria ocupată de nod} Programe cu liste:
program liste_simplu_inlantuite;
Pentru a elibera memoria ocupată de nodul care va fi şters mai avem uses crt;
type pnod=^nod;
nevoie de un pointer spre acest nod. După ce s-a făcut ruperea nod=record
legăturilor se eliberează memoria cu dispose. d:integer;
urm:pnod;
end;
var cap,sfir,y:pnod;
b) Suprimarea nodului indicata de o variabilă pointer q (pentru liste op:char;
simplu inlantuite)se face astfel: x:integer;
procedure inserare_inceput(x:integer);
p:=q^.urmator;{se memorează legătura către nodul următor} var q:pnod;
q^:=q^.urm^;{se copiază conŃinutul nodului următor peste cel curent} begin
new(q);
dispose(p);{se dezalocă memoria} q^.d:=x;
Această metodă nu poate fi utilizată pentru ultimul nod din listă. q^.urm:=cap;
if cap=nil then sfir:=q;
cap:=q;
end;
Traversarea unei liste înlănŃuite (Listarea) procedure inserare_sfirsit(x:integer);
var q:pnod;
Dacă nodul de început al listei e indicat de variabila început, o begin
variabila auxiliara q, care parcurge toate nodurile listei până când if sfir=nil then inserare_inceput(x)
valoarea ei devine nil, permite accesul la fiecare nod şi efectuarea else
begin
operaŃiei specifice traversării. new(q);
q^.d:=x;
procedure listare (q:PointerNod); q^.urm:=nil;
begin sfir^.urm:=q;
sfir:=q;
while q<>nil do
end;
49
end; y:=y^.urm;
procedure sterge_nod_urmator(p:pnod); end;
var q:pnod; function palindrom(x:pnod):boolean;
begin var f:boolean;
q:=p^.urm; begin
p^.urm:=p^.urm^.urm; f:=true;
dispose(q); y:=cap;
end; pal(x,f);
procedure sterge_nod_curent(var p:pnod); palindrom:=f;
var q:pnod; end;}
begin function palindrom(x:pnod):boolean;
if q<>nil then var f:boolean;
begin begin
q:=p^.urm; if x^.urm<>nil then palindrom:=palindrom(x^.urm)
p^:=p^.urm^; else palindrom:=true;
dispose(q); if x^.d<>y^.d then palindrom:=false;
end; y:=y^.urm;
end;
function cauta(x:integer):pnod; end;
var q:pnod; BEGIN
begin cap:=nil;sfir:=nil;
q:=cap; repeat
while (q<>nil)and(q^.d<>x)do q:=q^.urm; clrscr;
cauta:=q; writeln('1..Adaugare');
end; writeln('2..Afisare');
procedure afisare; writeln('3..Sterge dupa');
var q:pnod; writeln('4..Sterge');
begin writeln('5..Palindrom');
q:=cap; write('Dati optiunea:');readln(op);
while q<>nil do case op of
begin '1':begin write('Dati
writeln(q^.d); x:');readln(x);inserare_sfirsit(x);readln;end;
q:=q^.urm; '2':begin afisare;readln;end;
end; '3':begin write('Dati
end; x:');readln(x);y:=cauta(x);sterge_nod_urmator(y);readln;
end;
{procedure pal(x:pnod;var f:boolean); '4':begin write('Dati
begin x:');readln(x);y:=cauta(x);sterge_nod_curent(y);readln;e
if x^.urm<>nil then pal(x^.urm,f); nd;
if x^.d<>y^.d then f:=false;
50
'5':begin sf^.urm:=q;{ultimul din lista indica catre nodul nou
y:=cap;writeln('Palindrom=',palindrom(cap));readln;end; introdus}
end; sf:=q;{nodul nou introdus devine ultimul din lista}
until op='e'; end;
END. end;
51
end;
procedure sterge_curent(p:pnod);
begin procedure afisare_coada_cap;
if p<>nil then {daca avem ce sterge} var q:pnod;
begin begin
if p^.ant<>nil then {daca nodul anterior exista q:=sf;
atunci} while q<>nil do
p^.ant^.urm:=p^.urm{acesta indica catre nodul begin
urmator} writeln(q^.data);
else cap:=p^.urm;{daca nu exista atunci p e q:=q^.ant;
primul nod, deci cap va indica catre nodul urmator} end;
if p^.urm<>nil then {daca nodul urmator exista end;
atunci}
p^.urm^.ant:=p^.ant {acesta va indica catre begin
nodul anterior} repeat
else sf:=p^.ant; {daca nu exista atunci p e clrscr;
ultimul din lista, deci sf va indica catre nodul writeln('1..Adaugare la inceput');
anterior lui p} writeln('2..Adaugare la sfirsit');
dispose(p);{dezalocam memoria} writeln('3..Stergere');
end; writeln('4..Afisare');
end; writeln('5..Adaugare inaintea unui nod');
function cauta(x:integer):pnod; writeln('6..Adaugare dupa un nod');
var q:pnod;f:boolean; writeln('7..Exit');
begin readln(o);
q:=cap;f:=false; case o of
while (q<>nil)and (not f) do '1':begin
if q^.data=x then f:=true write('Dati elem. de introdus:');readln(k);
else q:=q^.urm; adaug_la_inceput(k);
cauta:=q; end;
end; '2':begin
write('Dati elem. de introdus:');readln(k);
procedure afisare_cap_coada; adaug_la_sfirsit(k);
var q:pnod; end;
begin '3':begin
q:=cap; write('Dati elem. de sters:');readln(k);
while q<>nil do sterge_curent(cauta(k));
begin end;
writeln(q^.data); '4':begin
q:=q^.urm; afisare_cap_coada;readln;afisare_coada_cap;readln;end;
end; '5':begin
52
write('Dati elem. de introdus:');readln(k); procedure citire;
write('Dati elem. inaintea caruia se face var f:text;x,y:integer;
adaugarea:');readln(du); begin
adaug_inainte(k,cauta(du)); assign(f,'date.in');reset(f);
readln(f,n);
end; while not seekeof(f) do
'6':begin begin
write('Dati elem. de introdus:');readln(k); readln(f,x,y);
write('Dati elem. dupa care se face add(x,y);
adaugarea:');readln(du); end;
adaug_dupa(k,cauta(du)); close(f);
end;
end; function grad(v:integer):integer;
end; var p:pnod;g:integer;
until o='7'; begin
end. p:=a[v];g:=0;{gradul lui v este egal cu nr de noduri
din lista a[v]}
program vector_de_liste; while p<>nil do
type pnod=^nod; begin
nod=record{nodul istei} inc(g);p:=p^.urm;
x:integer; end;
urm:pnod; grad:=g;
end; end;
var a:array[1..100] of pnod;{vectorul de capete ale
listei} BEGIN
n,i:integer; citire;
procedure ad(x:integer; var c:pnod);{adauga elementul x writeln('Gradele varfurilor sunt:');
in lista cu capul c} for i:=1 to n do
var p:pnod; writeln('varful ',i,' are gradul ',grad(i));
begin
new(p); END.
p^.x:=x;
p^.urm:=c;
c:=p;
end;
procedure add(x,y:integer);{adauga muchia x-y}
begin
ad(x,a[y]);
ad(y,a[x]);
end;
53
11.3.2 Liste particulare procedure push(x:integer);{introducere in stiva}
var a:pnod;
begin
Stiva new(a);{alocam memorie}
a^.d:=x;{memoram informatia}
Functioneaza dupa principiul LIFO (Last In First Out) - „Ultimul a^.urm:=cap;{punem valoarea pe prima pozitie}
intrat primul iesit” cap:=a;
end;
Atat inserarea cat si adaugarea de elemente in stiva se face de la un function pop:integer;{scoate elementul din virful
singur capat: stivei,daca e goala returneaza -maxint}
Ultimul nod introdus a fost 3. Varful stivei retine adresa ultimului var a:pnod;
nod, iar daca stiva e vida retine nil. begin
pop:=-maxint;
if cap<> nil then
V begin
a:=cap;{punem un pointer catre cap}
pop:=cap^.d;{memoram valoarea din virful stivei}
3 cap:=cap^.urm;{cap "coboara" cu o pozitie}
dispose(a);{dezalocam memoria}
end;
2 end;
procedure afisare;
var a:pnod;
1 begin
a:=cap;
while a<>NIL do
Operatiile permise sunt: begin
- adăugarea unui element in stiva (operatia push); writeln(a^.d);
- eliminarea unui element din stiva(operatia pop); a:=a^.urm;
end;
- verificarea daca stiva e goala (is_empty); writeln;
end;
program stiva; begin
type pnod=^nod;{pnod=pointer la nodul listei} repeat
nod=record write('Dati valoarea ce se introduce:');readln(x);
d:integer;{data ce se intoduce in stiva} push(x);
urm:pnod;{legatura catre urmatorul nod} until x=0;{citim valori pina cind se introduce 0}
end; repeat
var cap:pnod;{cap=capul listei(stivei)} afisare;{afisam stiva}
x:integer; readln;{asteptam apasarea tastei <ENTER>}
54
x:=pop; if cap=nil then cap:=p
writeln('Am scos:',x) else sf^.urm:=p;
until x=-maxint;{scoatem elemente si afisam pina golim sf:=p;
stiva} end;
end. close(f);
repeat
clrscr;
Coada
writeln('0..Afisare');writeln('1..Adaugare');
Intr-o coada inserarea se face la unul din capete, iar stergerea la writeln('2..Extragere');writeln('3..Test');
celalalt capăt. FuncŃionează după principiul FIFO (Firs In First writeln('4..Exit');readln(op);
Out). Pentru alocarea dinamica inlantuita a cozii o variabila v va case op of
retine adresa elementului ce va fi scos, iar variabila sf va retine adresa '0':begin
p:=cap;
ultimului element introdus in coada. while p<>nil do
v sf begin
writeln(p^.d);p:=p^.urm;
end;
1 2 3 4 readln;
end;
'1':begin
Se folosesc aceleaşi operaŃii ca si la stiva. write('Dati elem:');readln(s);
new(p);p^.d:=s;p^.urm:=nil;
if cap=nil then cap:=p
else sf^.urm:=p;
program coada; sf:=p;
uses crt; end;
type pnod=^nod; '2':if cap<>nil then
nod=record begin
d:string;urm:pnod; writeln('Data:',cap^.d);
end; p:=cap;cap:=cap^.urm;dispose(p);
var cap,sf,p,q:pnod; readln;
f:text;op:char;s:string; end;
begin '3':if cap=nil then writeln('Goala') else
assign(f,'date.txt'); writeln('nu e goala');
reset(f); end;
while not eof(f) do until op='4';
begin rewrite(f);
new(p); p:=cap;
readln(f,s); while p<>nil do
p^.d:=s;p^.urm:=nil; begin
55
writeln(f,p^.d); end
p:=p^.urm; else
end; begin
close(f); a^.urm:=endl^.urm;
end. endl^.urm:=a;
end;
endl:=a;
Liste circulare end;
procedure citire;
Fie o lista liniara L. Stiind ca variabila de tip pointer cap var i:integer;
memoreaza adresa primului nod , iar sf adresa ultimului element din s:string;
begin
lista se pune problema ce s-ar intampla daca ar avea loc operatia write('Dati nr. de copii:');
sf^.urmator :=cap. Se observa ca dupa aceasta operatie lista nu va readln(n);
mai avea practic inceput si sfarsit, o astfel de lista se numeste lista for i:=1 to n do
circulara. begin
La fel ca la listele liniare si aici se poate face adaugarea sau write('Dati copilul ',i,' :');readln(s);
adaug(s);
eliminarea de noduri din lista, sau parcurgerea listei pornind da la un end;
anumit element ( Principul este acelasi ca si la listele liniare ). write('Dati nr. k:');readln(k);
Observatie ! o lista circulara cu un singur element retine in campul end;
« urmator » adresa sa. Ex cap^.inf :=4 ; cap^.urmator :=cap ; procedure sterge(x:pnod);
var a:pnod;
begin
program joc;
a:=x^.urm;{a=nodul(copilul) care se sterge(iasa din
type pnod=^nod;{pnod=pointer la nodul listei}
joc) }
nod=record
writeln(a^.d);{tiparim numele copilului}
d:string;{numele copilului}
x^.urm:=x^.urm^.urm;{nodul din fata lui 'a' pointeaza
urm:pnod;{legatura catre urmatorul nod}
catre cel de dupa 'a'}
end;
dispose(a);
var cap,endl:pnod;{cap=capul listei}
end;
n,k:integer;
procedure joc;
procedure adaug(s:string);
var a,p:pnod;
var a:pnod;
i:integer;
begin
begin
new(a);
p:=endl;
a^.d:=s;
while p^.urm<>p do
if cap=nil then begin
begin
cap:=a;
for i:=1 to k-1 do
cap^.urm:=cap;
p:=p^.urm;
56
sterge(p);
end;
writeln('A cistigat ',p^.d);
end;
begin
citire;
joc;
end.
57