Sunteți pe pagina 1din 18

Curs 3 - Structuri de date

Structura de tip listă liniară. Structuri dinamice de date.


1. Prezentarea structurii
 O listă liniară este o colecţie de n0 noduri, X1, X2...Xn aflate într-o relaţie de ordine. Astfel,
X1 este primul nod al listei, X2 este al doilea nod al listei... Xn este ultimul nod.
 Listele sunt structuri de date generale ce ne permit păstrarea datelor, în memoria
internă, pentru mai multe obiecte. Datele despre obiecte corespund nodurilor listei.
Sunt folosite tipic pentru prelucrări directe de date în memorie sau pentru stocarea
temporară a unor date din fişiere, în scopul prelucrării.
 Operaţiile permise sunt:

 Accesul la oricare nod al listei în scopul citirii sau modificării informaţiei


conţinute de acesta.
 Adăugarea unui nod, indiferent de poziţia pe care o ocupă în listă.
 Stergerea unui nod, indiferent de poziţia pe care o ocupă în listă.
 Schimbarea poziţiei unui nod în cadrul listei, eventual ordonarea listei.

Există două metode de alocare (construire a nodurilor ) a unei liste liniare: alocarea secvenţială şi
alocarea înlănţuită. Cea mai bună metodă este cea înlănţuită.

1. Liste alocate secvenţial

Nodurile listei ocupă poziţii succesive în memorie. Acest tip de alocare l-am întâlnit des, de
câte ori am utilizat vectori.
Exemplu: un vector are n componente de tip real. Se cere să se sorteze vectorul crescător.
Algoritmul are ca dată de intrare o listă liniară, cu n noduri de tip real. Ieşirea este tot o listă liniară,
care are aceleaşi noduri, dar în altă ordine.
 Avantajul alocării secvenţiale este dat de faptul că programatorul are acces direct la oricare
din nodurile listei, la fel ca la componentele unui vector.
 Dezavantajul alocării secvenţiale este dat de faptul că operaţiile de adăugare, eliminare sau
schimbare de poziţie ale unui nod necesită un efort mare de calcul, ca în exemplul următor,
în care se elimină un nod:
Fie lista alocată secvential:
7 3 1 2 8 9 5 8 3 2 6

Eliminăm al doilea nod -conţinut 3.

7 1 2 8 9 5 8 3 2 6

7 1 2 8 9 5 8 3 2 6

Este obligatoriu ca nodurile următoare să fie deplasate catre stânga. Nu le mai studiem.
2. Liste alocate înlănţuit
Există două feluri de alocare înlănţuită: alocare simplu înlănţuită şi alocare dublu
înlănţuită. 1. O listă liniară simplu înlănţuită este o structură de forma:

info1 adr2 info2 adr3 infon nil

prim adr2 adrn


Semnificaţia notaţiilor folosite este următoarea:

 adr1, adr2, adr3... adrn reprezintă adresele celor n înregistrări;


 in1, in2, ...inn reprezintă informaţiile conţinute de noduri, de altă natură decât cele de adresă;
 ni1 -are semnificaţia ”nici o adresă” -elementul este ultimul în listă.
După cum observăm, fiecare nod, cu excepţia ultimului, reţine adresa nodului următor.

Alocarea dublu înlănţuită. Alocarea simplu înlănţuită permite parcurgerea listei într-un singur sens
{de la stânga la dreapta}- în cazul în care se doreşte ca lista să poată fi parcursă în ambele sensuri se
utilizează alocarea dublu înlănţuită. Aici fiecare nod reţine adresele predecesorului şi succesorului
său, aşa cum se vede în figura următoare:

nil in1 adr2 adr1 in2 adr3 adrn-1 inn nil

adr1 adr2 adrn


Dezavantajele alocării înlănţuite sunt:

1. Accesul la un nod al listei se face prin parcurgerea nodurilor care îl preced. Aceasta necesită un
efort de calcul.

2. Informaţiile de adresă, prezente în cadrul fiecărui nod ocupă memorie.


 Avantajele alocării înlănţuite sunt date de faptul că operaţiile de adăugare sau eliminare a
unui nod se fac rapid. Exemplele sunt date pentru lista liniară simplu înlănţuită, dar ne
permit să deducem modul de efectuare a operaţiilor respective pentru liste dublu înlănţuite.
 Folosirea memoriei de tip Heap care oferă u spaţiu mult mai mare.
a) adăugarea unui nod.

Fie lista:

3 adr2 7 adr3 9 nil

adr1 adr2 adrn

Dorim să adăugăm după nodul cu informaţia 3, un altul cu informatia 5.


Etapele sunt:
 Se alocă spaţiu în memorie pentru un nou nod -indiferent unde:

3 adr2 7 adr3 9 nil


adr1 adr2 adrn

adrt
 Se completează informaţiile pentru nodul creat –adresa acestuia va trebui să conţină adresa
nodului care trebuie să-i urmeze în listă:

3 adr2 7 adr3 9 nil


adr1 adr2 adrn

5 adr2

adrt

 Se modifică adresa nodului care precede nodul nou creat. Adresa trebuie să fie a nodului
nou creat:

in1 adrt in3 adr3 inn nil


adr1 adr3 adrn

in2 adr2
adr2 adr2
De acum, putem “privi” lista aşa cum am fost obişnuiţi:

3 adrt 5 adr2 7 adr2 9 nil


adr1
adrt adr2 adrn

b) Ştergerea unui nod.

Pentru a exemplifica operaţiile efectuate în acest caz vom folosi lista de mai sus, la care
ştergem al doilea nod (cel cu informaţia 5). Iată etapele:

 Informaţia de adresă a nodului care îl precede trebuie să reţină adresa nodului


următor:

3 adrt 5 adr2 7 adr2 9 nil


prim adrt adr2 adrn

 Memoria ocupată de nodul care urmează a fi şters este eliberată.

3 adr2 7 adr2 9 nil


adr1 adr2 adrn
De acum, putem privi lista aşa cum am fost obişnuiţi.

3 adrt 7 adr3 9 nil


adr1 adr2 adrn

Observaţii:
 În cazul alocării înlăntuite, adresele de memorare ale nodurilor consecutive nu sunt
neapărat consecutive. Pentru a realiza acest lucru este suficient să analizati cazul stergerii
unui nod {sau acela al adăugării unui nod}.

 Prin alocarea memoriei pentru un nod înţelegem rezervarea spaţiului necesar memorării
informatiilor conţinute de acesta. Evident, se poate aloca memorie doar dacă există memorie
disponibilă, adică nu este ocupată de alte variabile.

 Prin eliberarea memoriei ocupate de un nod înţelegem că spaţiul ocupat de acesta devine
disponibil-este pus la dispoziţia programatorului, pentru ca, eventual, acesta să fie din nou
alocat.

 Este important să folosim termenii corect. De exemplu, nu putem folosi în loc de ”alocarea
memoriei” termenul ”crearea memoriei”, tot aşa cum nu este corect să folosim în loc de
”eliberarea memoriei” termenul ”ştergere a memoriei”.

2. Implementarea alocării înlănţuite prin utilizarea vectorilor. Liste statice.


Lista liniară este alcătută din mai multe noduri între care există o relaţie de ordine, în cazul
alocării înlănţuite, informaţia memorată de fiecare nod va cuprinde şi un câmp de adresă -în cazul
alocării simplu înlănţuite- sau două câmpuri de adresă -în cazul alocării dublu înlănţuite.În acest
paragraf vom studia implementarea alocării simplu înlănţuite.

 Iată cum se descrie informaţia dintr-un nod, în cazul listelor simplu înlănţuite, atunci când
acesta reţine un număr întreg.

Type Adresa=Integer;
info adresa nodului următor
Nod=record

info:integer;

adr_urm:Adresa;

end;

Pentru a nu face confuzie între informatia de adresă, care este tot de tip integer, şi restul
informaţiei memorate, am ”rebotezat” tipul integer.
 Pentru memorarea listei folosim un vector care are componentele de tip Nod, descris mai
jos:

Lista=array[1..1000] of Nod;
Var L:lista;
Din descriere rezultă că lista poate avea cel mult 1000 de noduri. Acesta este spaţiul
disponibil. Spaţiul disponibil se gestionează prin următoarele variabile:

 nr_elem:integer; -reprezintă numărul de noduri conţinute la un moment dat de listă.

 ocupat:array[1...1000] of Adresa; reţine 1 dacă componenta corespunzătoare din L


memorează un nod, sau 0 în caz contrar.

L 7 3 5 4 1 5 4 0
1 2 3 4 5 6
ocupat 1 0 1 1 1 0

1 2 3 4 5 6
Figura anterioară prezintă modul în care este memorată o listă cu 4 noduri, într-un vector cu 6
componente. Lista este: 7, 5, 1, 4

 Funcţia următoare testează dacă există spaţiu disponibil pentru alocarea unui nou nod:
function Exista_spatiu:boolean;
begin
Exista_spatiu:=nr_elem<l000;
end;

 Alocarea propriu-zisă se face prin procedura următoare:


procedure Aloca(var x:Adresa);
var i:Adresa;
begin
i:=l;
while ocupat[i]<>0 do i:=i+l;
x:=i;
ocupat[i]:=1;
nr_elem:=nr_elem+1;
end;
Procedura caută prima componentă liberă (care nu memorează nici un nod), în momentul
găsirii acesteia, se marchează vectorul ocupat şi se returnează adresa unde a fost găsită (indicele în
vector). În exemplul din figură prima componentă disponibilă este de indice 2. Procedura va returna
2 (adresa), iar ocupat [2] va reţine 1
 Eliberarea spaţiului la ştergerea unui nod al listei se face prin procedura elibereaza:

procedure elibereaza(x:adresa);
begin
ocupat[x]:=0;
nr_elem:=nr_elem-1;
end;
 Procedura adaugare are rolul de a adăuga la sfârsitul listei un nod, care reţine valoarea
transmisă de variabila val. Programul lucrează cu lista pornind de la adresa primului nod
memorat, adresă care se găseşte în v. De asemenea, pentru uşurinţa prelucrării se reţine şi
adresa ultimului nod sf.

procedure adaugare(var v:integer; val:integer);


var c:integer;
begin
if v=0
then
begin
Aloca(v);
L[v].info:=val; L[v] .adr_urm:=0;
sf:=v;
end
else
if Exista_spatiu
then
begin
Aloca(c);
L[sf] .adr_urm:=c; L[c].info:=val;L[c].adr_urm:=0;
sf:=c;
end
else writeln(‘Lipsa spatiu‘);
end;

Procedura tratează diferit cazurile în care lista este vidă, deci se creează primul nod al ei şi
cazul în care adăugarea se face la o listă nevidă,

 În primul caz se alocă nodul, se completează cu informatia numerică, iar câmpul de adresă
va reţine 0.

 În al doilea caz, se testează existenţa spaţiului, iar în caz că acesta există se alocă spaţiul
pentru nod. Nodul reţine 0, pentru adresa nodului următor (pentru că este ultimul în listă).
Ultimul nod al listei (cu adresa sf) va reţine adresa nodului nou creat, iar variabila sf va
reţine adresa nodului nou creat.

 Procedura inserare_dupa inserează un nod după un altul, care reţine valoarea numerică val.
Noul nod retine valoarea numerică val1.

procedure inserare_dupa (v:adresa;val,val1:integer);


var c,d:adresa;
begin
if Exista_spatiu
then
begin
c:=v;
while L[c].info<>va1 do c:=L[c].adr_urm;
Aloca(d);
L[d].info:=val1;L[d].adr_urm:=L[c].adr_urm;L[c].adr_urm:=d;
end;
else writeln(‘Nu exista spatiu‘);
end;

În cazul în care există spaţiul necesar se procedează astfel:


 Se caută nodul care reţine valoarea val.
 Se alocă spaţiul pentru nodul nod;
 Noul nod va memora val1, iar ca adresă a nodului următor va memora valoarea reţinută de
câmpul adr_urm a nodului care reţine val.
 Nodul care reţine val va memora la câmpul de adresă adresa nodului nou creat.

 Procedura inserare_inainte inserează un nod înaintea altuia care reţine o valoare dată,
transmisă prin val:

procedure inserare_inainte(var v:adresa;val,val1:integer);


var c,d:adresa;
begin
if Exista_spatiu
then
if L[v].info=val
then
begin
Aloca(d); L[d].info:=val1; L[d].adr_urm:=v; v:=d;
end
else
begin
c:=v;
while L[L[c].adr_urm].info<>val do c:=L[c].adr_urm;
Aloca(d);
L[d].info:=val1;L[d].adr_urm:=L[c].adr_urm;L [c].adr_urm:=d;
end
else writeln(‘Nu exista spatiu‘);
end;
 Procedura sterg şterge nodul care memorează valoarea transmisă prin val:

procedure sterg(var v:adresa;val:integer);


var c,aux:adresa;
begin
if L[v].info=val
then
begin
aux:=v;v:=L[v].adr_urm;
end
else
begin
c:=v;
while L[L[c].adr_urm].info<>val do c:=L[c].adr_urm;
aux:=L[c].adr_urm;L[c].adr_urm:=L [aux].adr_urm;
if aux=sf then sf:=c;
end;
elibereaza(aux);
end;

 Afişarea listei se face cu procedura următoare:


Procedure listare(v:Adresa);
Var c:Adresa;
begin
c:=v;
while c<>0 do
begin
write(L[c].info,’ ’);
c:=L[c].adr_urm;
end;
writeln;
end;

Observaţii:
 Alocarea înlănţuită prin utilizarea vectorilor tine deja de istoria informaticii. Cu adevărat,
pentru alocarea înlănţuită a unei structuri se utilizează o zonă de memorie, special rezervată
în limbajele de programare actuale, numită HEAP. VOM PREZENTA, MAI DEPARTE, SOLUTIA
DINAMICĂ .
3. Implementarea alocării înlănţuite dinamic. Structuri dinamice de
date. -cea mai buna variantă.

3.1.Variabile statice, variabile dinamice

Variabilele pot fi statice sau dinamice. Cele statice sunt alocate în timpul compilării, în zone
bine definite de memorie. Structura, tipul şi locul lor din memorie nu se pot modifica în timpul
execuţiei programului. Statice sunt toate variabilele folosite până acum.

Limbajul Pascal oferă posibilitatea alocării memoriei în timpul executării programului,


pentru unele variabile, numite dinamice, în funcţie de necesitate şi de asemenea, există posibilitatea
eliberării memoriei ocupate de ele.. De asemenea, accesul la astfel de variabile nu se face direct. Lor
li se pune în corespondenţă un tip de referinţă, în mod biunivoc, despre ceea ce se spune că se referă
sau indică („pointează”).

Variabila de tip referinţă poate conţine referiri numai la variabila dinamică care i-a fost
pusă în corespondenţă. Referirea se realizează prin memorarea în variabila de tip referinţă a adresei
unde este stocată variabila dinamică. Corespondenţa între variabila dinamică şi tipul de referinţă
permite cunoaşterea structurii variabilei dinamice.
Pentru variabilele de tip referinţă se va aloca, în timpul compilării, un spaţiu de memorie de
4 octeţi, care va conţine adresa de memorie a variabilei dinamice referite.
Variabilele dinamice se alocă într-o zonă de memorie numită heap, diferită de zona fixă a
programului, unde se memoreză variabilele statice.
O variabilă dinamică referită va ocupa un spaţiu de memorie corespunzător tipului ei: 2
octeţi pentru Integer, 6 octeţi pentru Real, 10 octeţi pentru un şir de 9 caractere (String[9]) etc.
Defirea unui tip referinţă

Definirea unui tip referinţă se poate face în secţiunea type astfel:

type tip_referinta = ^tip_variabila_dinamica;

(se citeşte ,,pointer la...").


Mulţimea valorilor de tip tip_referinta constă într-un număr nelimitat de adrese. Fiecare
adresă identifică o variabilă de tip tip_variabila_dinamica. La această mulţime de valori se mai
adaugă o valoare specială, numită nil, care nu identifică o variabilă.

la adresa 100 este 2500 = adresa variabilei referite

MEMORIA

Zona Heap
2500
programul
zona variabilelor varibila dinamică referită

o variabilă de tip referinţă4 octeţi =adresa unei variabile de tip


tip_variabila_dinamica
Exemplu:
tip pReal = ^Real;
var pr : pReal;
variabila dinamica referită (6 octeţi)
MEMORIA

programul Zona Heap

pr pr^

 Procedura New alocă spaţiu în HEAP pentru o variabilă dinamică. După alocare, adresa
variabilei se găseste în p
procedure New(var P: Pointer)

 Procedura Dispose eliberează spaţiul rezervat pentru variabila a cărei adresă este reţinută în
p. După eliberare, conţinutul variabilei p este nedefinit.

procedure Dispose(var P: Pointer)

Avantajele utilizării variabilelor dinamice


 Memorarea unei variabile dinamice se realizează în două faze:
-alocarea zonei de memorie pentru variabila dinamică, cu procedura New;
-memorarea efectivă, adică depunerea, la adresa pregătită, a datelor corespunzătoare
variabilei dinamice.
 Eliberarea zonei de memorie corespunzătoare unei variabile dinamice, ocupată cu procedura
New, se realizează cu procedura Dispose.

Exemplu:

program TestPointer;
type complex = record
re, im: Real
end;

pComplex =^complex;
var pz: pComplex; sau
pz : ^complex;
begin
New(pz); pz^.re: =l .2; pz^. im:=5 . 6;
WriteLn ('Nr. complex: ',pz^.re, ^ ' ', pz^.im);
Dispose(pz); ReadLn
end.
Cu variabilele dinamice se pot executa toate operaţiile posibile având datele de respectivul tip.

Printre avantajele utilizării pointerilor se numără:


 folosirea unui spaţiu de memorie redus, în cazul utilizării unor structuri complexe de date;
 folosirea mai eficientă a spatiului de memorie, prin eventuala reutilizare a sa (după Dispose).
Exemplu:

type persoana = record


nume, prenume: String; {2*256 octeti = 512 octeti}
virsta: Integer {2 octeti, deci 514 octeti, in total}
end;
pPersoana = ^persoana; { 4 octeti}
mult_pers_1 =array [1..50] of persoana;
mul_pers_2 = array [1..50] of pPersoana;
var M1:mult_pers_1; {50*514=25700 octeti}
M2: mult_pers_2 {50*4=200 octeti, restul e in heap care este foarte mare ! }

 Următorul program creează o listă liniară simplu înlănţuită cu 3 noduri care reţin 1 2 3.

program exemplu;
type Adresa=^Nod;
Nod=record
info:integer;
adr_urm:Adresa;
end;
var c,d,v:Adresa;
begin
New(v); v^.info:=l;
New(c); c^.info:=2;
v^ .adr_urm: =c ;
New(d);
d^.info:=3;
d^.adr_urm:=nil;
c ^.adr_urm:=d;
{listare}
c: =v;
while c<>nil do
begin
write(c^.info,’ ‘);
c:=c ^.adr_urm;
end;
writeln;
end.

Analizăm programul pas cu pas:


New(v); v^.info: =1
v 1

Am alocat memorie în HEAP pentru un nod. Adresa este reţinută în v.

New(v); v^.info: =2
v 1

c 2

Am alocat memorie pentru alt nod. Adresa este reţinută în c

v 1
v^.adr_urm: =c;

c 2

Adresa următoare, pentru primul nod alocat va reţine adresa următorului nod alocat.

v 1
New(d);
d^.info:=3;d^.adr_urm:=nil;
c^.adr_urm: =d;
c 2

d 3 0

Am alocat spaţiu pentru al treilea nod. Acesta va reţine 3 în info şi nil (nici o adresă) pentru
adr_urm. De fapt, pentru nil se reţine 0, dar nu se poate lucra cu această valoare.

v 1
Din acest moment, se poate lucra cu
lista cunoscând doar adresa sa de
2 început (a primului nod) v.

3 0

Programul următor, prezintă modul de lucru cu o listă liniară simplu înlăntuită. Este identic
cu cel prezentat în paragraful anterior, singura diferentă este dată de faptul că lista este memorată în
HEAP.
program Lista_liniara;
Type Adresa=^Nod;
Nod=record
info:integer;
adr_urm:Adresa;
end;
var prim,ultim:Adresa;
i:integer;

procedure Adaugare(var prim:adresa;val:integer);


var p:Adresa;
begin
if prim=nil
then
begin
new(prim); prim^.info:=val; prim^.adr_urm:=nil;
ultim:=prim;
end
else
begin
New(p); ultim^.adr_urm:=p;
p^.info:=val; p^.adr_urm:=nil;
ultim:=p;
end
end;

procedure inserare_dupa(prim:adresa;val,val1:integer);
var p,q:adresa;
begin
p:=prim;
while p^.info<>val do p:=p^.adr_urm;
new(q); q^.info:=val1; q^ .adr_urm:=p^.adr_urm; p^.adr_urm:=q;
if q^.adr_urm=nil then ultim:=q;
end;

procedure inserare_inainte(var prim:adresa;val,vall:integer);


var p,q:adresa;
begin
if prim^.info=val
then
begin
new(q);
q^.info:=vall; q^.adr_urm:=prim;
prim:=q;
end
else
begin
p:=prim;
while p^.adr_urm^.info<>val do p:=p^.adr_urm;
new(q);q^ .info:=vall; q^ .adr_urm:=p^.adr_urm; p^.adr_urm:=q;
end
end;

procedure sterg(var prim:adresa;val:integer);


var p,aux:adresa;
begin
if prim^.info=val
then
begin
aux:=prim; prim:=prim^. adr_urm;
end
else
begin
p:=prim;
while p^.adr_urm^.info<>val do p:=p^.adr_urm;
aux:=p^. adr_urm; p^. adr_urm:=aux^. adr_urm;
if aux=ultim then ultim:=p;
end;
dispose(aux);
end;

procedure listare(prim:Adresa) ;
Var p:Adresa;
begin
p:=prim;
while p<>nil do
begin
write(p^.info, ' ');
p:=p^.adr_urm;
end;
writeln;
end;

begin
{se construieste lista}
for i:=1 to 10 do Adaugare(prim,i);
writeln('lista asa cum a fost creata');
listare(prim);
writeln('inserez dupa 5 11');
inserare_dupa(prim,5,11);
listare(prim);
end.

Observaţii:
 Alocarea dinamică a memoriei prezintă avantajul că programul utilizează o zonă de memorie
oricum rezervată, numită HEAP. În acest fel,programul are ”la dispozitie” mai multă
memorie.

 Alocarea înlănţuită prin utilizarea alocării dinamice prezintă avantajul că alocarea şi


eliberarea memoriei se face cu proceduri ale limbajului -nu este nevoie ca programatorul să
scrie propriile rutine. S-ar putea spune că, în comparaţie cu alocarea prin intermediul
vectorilor, prezintă numai avantajem dar se depune un efort de programare mult mai mare.

Aplicaţii exemplificative pentru lucrul cu liste simplu înlănţuite.


Operatii de prelucrare.
Se consideră datele despre elevii unei clase : nume, prenume, media generală a fiecărui elev.
Se cere realizarea unei aplicaţii care să permită stocarea datelor într-o structură de tip lista
simplu înlănţuită. Aplicaţia va permite crearea listei (în două variante), afişarea unei liste cu
elevii, lista ordonata dupa medie, determinarea mediei generale a clasei, adăugarea unui nou
elev şi ştergerea unui elev cunoscându-i numele.

1. Implementare folosind o structură de tip listă simplu înlănţuită:


Program Liste ;
uses crt;
Type Lista=^Nod;
Nod=Record
Info :Integer;
Urm:Lista;
end;
Var Prim :Lista;
X:Integer;
Optiune:Integer;
{Crearea unei liste liniare simplu inlantuita}

Procedure Creare (Var Prim :Lista);


Var P:Lista;
Raspuns :String[2];
begin
Prim :=nil;{ Se pleaca de la lista vida }
repeat
New(p); { Se rezerva memorie }
WriteLn('Dati informatia nodului :');
ReadLn(P^.info);
p^.urm := Prim; { Se leaga noul nod de lista adica de primul nod }
prim:=p; { Primul nod a devenit p }
WriteLn('Mai aveti noduri (DA/NU)?');
ReadLn(Raspuns);
until Raspuns='NU';
end;

{ Parcurgerea sau afisarea nodurilor unei l.l.s.i.}

Procedure Parcurgere(Prim :Lista);


Var P:Lista;
begin
P:=Prim;
while P<>NIL do
begin
WriteLn('Informatie :',p^.info);
p:=p^.urm;
end;
end;

{ Ordonarea unei l.l.s.i. }

Procedure Ordonare (Var Prim:Lista);


Var P:Lista;
K,Temp:Integer;
begin
repeat
k:=0;
p:=prim ;
while (p^.urm <>nil) do
begin
if p^.info >p^.urm^.info then
begin
temp:=p^.info;
p^.info:=p^.urm^.info;
p^.urm^.info:=temp;
k:=1;
end;
p:=p^.urm;
end;
until k=0;
end;
{Adaugarea unui nou nod in capul listei }

Procedure Inserare_Cap_Lista(Var Prim:Lista);


Var P:Lista;
begin
New(p); { Se rezerva memorie }
WriteLn('Dati informatia nodului :');
ReadLn(P^.info);
p^.urm := Prim; {Se leaga noul nod de lista adica de primul nod }
prim:=p; { Primul nod a devenit p }
end;

{Adaugarea unui nou nod intr-o pozitie oarecare cunoscand informatia X a nodului
dupa care se face inserarea}

Procedure Inserare_Poz_Oarecare(Var Prim:Lista;X:Integer);


Var P,Q:Lista;
begin
p:=prim;
while (P<>nil) and (p^.info<>X) do
p:=p^.urm ;
if P<>Nil then
begin
New(Q); { Se rezerva memorie }
WriteLn('Dati informatia nodului :');
ReadLn(Q^.info);
Q^.urm :=P^.urm;
P^.urm:=Q;
end
else
WriteLn('Nu exista nodul dat :');
end;

Procedure Creare1 (Var Prim :Lista);


Var P:Lista;
Raspuns :String[2];
begin
Prim :=nil;{Se pleaca de la lista vida }
repeat
Inserare_Cap_Lista(Prim);
WriteLn('Mai avaeti noduri (DA/NU)?');
ReadLn(Raspuns);
until Raspuns='NU';
end;

{Stergerea unui nod din lista}


Procedure Stergere(Var Prim :Lista;X:Integer);
Var P,Q :Lista;
Begin
{ Se cauta nodul care se sterge}
P:=Prim;
q:=prim;
while(p<>Nil) and (p^.info<>X) do
begin
q:=p; {Se retine nodul anterior }
p:=p^.urm;
end;
if P<>Nil then
begin
{ S-a gasit nodul}
if p=prim then
begin
{ Este primul nod }
prim:=p^.urm ;
Dispose(P);
WriteLn('S-a sters primul nod cu informatia :',X);
end
else
begin
{ Este un nod oarecare }
q^.urm :=p^.urm ;
Dispose(p);
WriteLn('S-a sters un nod cu informatia :',X);
end
end
else
WriteLn('Nu exista nici un nod cu informatia ',X) ;
end;

begin
clrscr;
repeat
WriteLn('1.CREARE');
WriteLn('2.PARCURGERE');
WriteLn('3.ORDONARE');
WriteLn('4.INSERARE FATA');
WriteLn('5.INSERARE OAREC');
WriteLn('6.Stergere');
WriteLn('7.IESIRE');
Write('Alege optiunea ');
ReadLn(Optiune);
case Optiune of
1:Creare(Prim);
2:Parcurgere(Prim);
3:Ordonare(Prim);
4:Inserare_Cap_Lista(Prim);
5:begin
Write('dati informatia nodului dupa care inserati :');
ReadLn(X);
Inserare_Poz_Oarecare(Prim,X);
end;
6:begin
Write('dati informatia nodului care se sterge :');
ReadLn(X);
Stergere(Prim,X);
end;
end;
until Optiune=7;

end.
Aplicaţii.
1. Creati o lista s.i. care sa contina datele despre studentii unei grupe: nume, prenume, grupa, medie.
Se va crea lista si se va afisa.

2. Într-un fişier se gasesc datele despre rezultatele la bacalaureat:nume,prenume,medie. Sa se


construiasca un program, ce foloseşte liste simplu inlantuite, alocate dinamic, pentru prelucrarea
datelor despre candidati. Programul va permite:
-preluarea candidatilor din fisier si depunerea lor in memorie intr-o lista s.i. pentru prelucrare.
-preluarea interactiva de noi candidati: procedura de Adaugare
-afisarea tuturor candidatilor.
-Cautarea unui candidat cunoscându-i numele si prenumele.
-crearea unui fisier cu candidatii ordonati alfabetic si a unuia cu candidatii ordonati descrescator
dupa medie.
-afisarea mediei generale pentru toti candidatii.
-stergerea unui candidat cunoscându-i numele si prenumele.

Tema- Incercati crearea unei liste ordonate de la inceput.

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