Documente Academic
Documente Profesional
Documente Cultură
STRUCTURI DE DATE
1. Conceptul de dată
De foarte multe ori în realitate, datele apar sub forma unor colecţii de date asupra unor
mulţimi de date pe care însă s-a definit o anumită organizare menită să faciliteze prelucrarea.
O colecţie de date pe care s-a definit o anumită organizare, o numită structură şi căreia îi
este specific un anumit mod de selecţie şi identificare, poartă denumirea de structură de date.
Componetele unei structuri de date pot fi identificate prin nume (selecţia prin nume) sau
prin ordinea pe care o ocupă în cadrul structurii în conformitate cu structura existentă.
Dacă accesul la o anumită componentă a unei structuri de date se poate face fără să se
ţină seama de celelalte componente, vom spune că structura de date este cu acces direct. Un
exemplu este cazul unui tablou de elemente la care se poate accesa oricare element prin poziţia
sa în cadrul tabloului, de ex. A[5]
În schimb, dacă accesul la o componentă a structurii se face ţinând cont de alte câmpuri
ale structurii în conformitate cu ordinea structuriii (printr-un proces de traversare) atunci vom
spune că structura este cu acces secvenţial (este cazul unui fişier text).
2 Curs 1 - STRUCTURU DE DATE
Structurile de date pot fi create pentru memoria internă sau externă (fişiere pe disc
magnetic sau banda magnetică; acestea poartă denumirea de fişier).
Structurile interne au un caracter de date temporare, ele dispar odată cu oprirea
programului, încetarea activităţii de prelucrare, iar cele externe au un caracter de date
permanente, care nu se pierd odată cu întreruperea tensiunii de alimentare.
Dacă pe lângă componentele structurii se înregistrează pe suport şi alte date suplimentare
care să materializeze pe suport relaţia de ordonare, atunci structura de date respectivă este
explicită, în caz contrar este implicită.
Structura de date de tip tablou este o structură implicită; listele liniare simplu înlănţuite
sunt structuri explicite de date.
Asupra structurilor de date se pot efectua mai multe operaţii care se referă la valorile
datei şi/sau la structură.
Cele mai frecvente operaţii pot fi:
- operaţia de creare care constă în memorarea pe suportul de memorie a structurii de
date în forma sa iniţială
- operaţia de consultare care constă în accesul la elementele structurii în vederea
prelucrării valorilor acestora
- operaţia de actualizare care constă în adăugarea de noi elemente, ştergerea
elementelor care nu mai sunt necesare şi modificarea valorilor unor componente ale
structurii
- operaţia de actualizare constă în modificarea structurii de date
- operaţia de sortare care presupune aranjarea, ordonarea elementelor unei structuri
într-o anumită ordine precizată de valorile date
- operaţia de descompunere care constă în descompunerea unei structuri de date în
două sau mai multe structuri
- operaţia de fuzionare – combinarea a două sau mai multe structuri la fel ordonate în
una singură
- operaţia de copiere – realizarea unei copii a structurii de date, de regulă pe un alt
suport de memorie.
Operaţiile care pot fi efectuate asupra unei structuri de date şi eficienţa cu care acestea
pot fi utilizate depind în mare măsură de natura relaţiilor de ordonare şi modul în care acestea
sunt ordonate pe suport. Din acest punct de vedere, operaţiile constituie element distinctiv al unei
structuri de date, deci o proprietate a structurii.
Toate structurile de date la fel organizate şi pe care s-au definit aceleaşi operaţii, poarta
numele de tip de structură de date. Dacă analizăm însă operaţiile care se efectuează asupra
unei structuri de date, vom putea vedea că toate acestea se reduc la executarea, eventual repetată,
a unui grup de operaţii specifice numite operaţii de bază.
Prin tip de structură de date vom înţelege o colecţie de date (ordonată) pe care s-a
definit un grup de operaţii de bază cu o anumită semantică. Cele mai avansate metode de
structurare de bază sunt tablourile şi structurile.
Structurile avansate de date nu se descriu ca structuri statice deoarece ele se generază în
mod dinamic în timpul procesului de prelucrare – se vor numi structuri dinamice de date.
Orice algoritm primeşte date de intrare, le prelucrează şi obţine date de ieşire. În fiecare caz,
datele de intrare, datele intermediare - cele create în timpul prelucrării - şi datele de ieşire sunt
structurate (organizate) într-un anumit fel care corespunde intrării, necesităţilor de prelucrare sau
a celor de utilizare ulterioară.
Pentru a veni în sprijinul programatorilor, limbajele de programare evoluate (de exemplu
Pascal, C) pun la dispoziţia acestora posibilitatea organizării datelor în anumite "şabloane"
numite tipuri de date. Mai precis, prin tip de date se înţelege:
• o mulţime de valori;
• o regulă de codificare a acestora;
• o mulţime de operaţii definite pe mulţimea datelor.
La rândul lor, tipurile de date pot fi:
STRUCTURI DE DATE - Curs 1 3
• simple - descriu date care apartin unor mulţimi care nu sunt rezultate ca produs
cartezian al altor mulţimi. Exemplu: integer (pascal), respectiv int (C).
• structurate -descriu date care apartin unor mulţimi rezultate ca produs
cartezian al altor mulţimi.
Exemple:
1. În limbajul Pascal: În limbajul C:
type Rational=record typedef struct { int p,q;
p,q:integer; } Rational;
end
Prin tipul de mai sus se descrie structura unei variabile capabilă să reţina numere raţionale.
2. În limbajul Pascal: În limbajul C:
type vector=array [1..100] of real; typedef float vector[100];
Practica impune utilizarea unor structuri ale datelor de o mare varietate, care nu se
suprapun întotdeauna peste tipurile care pot fi descrise prin limbaj, de obicei obţinându-se prin
combinarea celor elementare .
Prin structură de date vom înţelege un asamblu de date caracterizat prin relaţiile existente
între ele şi a operaţiilor care pot fi efectuate cu datele respective.
Vom numi nod o variabilă de un tip oarecare. De obicei, acest tip este structurat. După
caz, termenul nod poate fi înlocuit cu articol, înregistrare sau entitate.
În cele mai multe cazuri, "ansamblul de date" care alcătuieşte structura e alcătuit dintr-o
mulţime cu un număr variabil de noduri.
Lista liniară este o colecţie de n≥0 elemente de acelaşi tip denumite noduri ale căror
proprietăţi structurale se referă la poziţiile relative liniare unidimensionale.
Dacă n=0 lista este lista vidă
Dacă n≥1: se reprezintă a1, a2,…, an şi fiecare nod ai aparţine tipului de bază.
a1 – primul element; an – ultimul element; n=lungimea listei;
ai-1, ai ai – succesorul lui ai-1
ai, ai+1 ai – predecesorul lui ai+1
Principalele operaţii care se pot efectua asupra elementelor unei liste liniare sunt urmatoarele:
1) inserarea unui nou element în faţa elementului de pe poziţia i
2) suprimarea elementului de pe poziţia i
3) consultarea elementului de pe poziţia i
4) sortarea elementelor listei în ordinea valorilor unui anumit câmp – câmp cheie – precizată de
utilizator
4 Curs 1 - STRUCTURU DE DATE
La acest mod de implementare nodurile listei ocupă poziţii succesive în memorie. Acest tip de
alocare a fost utilizat frecvent, ori de câte ori s-au utilizat vectori.
În reprezentarea listelor prin intermediul tipului tablou, tipul listă se asimilează cu un
articol cu 2 componente:
- o componentă fiind un tablou ale cărui elemente vor fi elementele listei de
dimensiune aleasă astfel încât să poată să conţină cea mai mare listă posibilă care
poate să apară în respectiva aplicaţie
- a doua componentă (câmp) este un întreg care va preciza poziţia în tablou a ultimului
element al listei liniare.
Structura de date care va descrie o astfel de implementare a listelor liniare va fi:
În limbajul Pascal: În limbajul C:
CONST lung_max=…; # define lungime_max …
TYPE nod=…; typedef … nod;
lista=RECORD typedef struct {
elem:ARRAY[1..lung_max] of nod; nod elem[lung_max];
ultim:INTEGER; int ultim;
END; }lista;
elem
primul element
al 2-lea element lista
ultim
ultimul element
spaţiu
lungime neutilizat
maximă
Într-o listă astfel implementată, se pot efectua următoarele operaţii:
Adăugarea de noi elemente la sfîrşitul listei liniare. Această operaţie se poate face uşor
într-un număr finit de paşi până la completarea în întregime a tabloului rezervat listei. Dacă se
încearcă inserarea unui nou element într-o listă care a ocupat în întregime tabloul se va semnala
un fenomen numit depăşire.
Inserarea unui nou element într-o poziţie din interiorul listei. Această operaţie presupune
deplasarea cu o poziţie a tuturor elementelor de pe poziţiile următoare poziţiei de inserat spre
sfârşitul listei pentru a elibera poziţia de inserat, după care noul element se va insera pe poziţia
eliberată. Acest proces necesită un timp direct proporţional cu numărul de elemente.
Ştergerea unui element de la sfârşitul listei. Această operaţie se poate face cu uşurinţă
decrementând contorul ultim;
Ştergerea unui unui element din interiorul listei. Această operaţie presupune că toate
elementele care se află după acest element se vor deplasa spre începutul tabloului pentru a ocupa
spaţiul eliberat, după care trebuie să se decrementeze contorul ultim. Dacă se încearcă
STRUCTURI DE DATE - Curs 1 5
suprimarea unui element dintr-o listă vidă, se va semnala depăşirea acestui element prin
fenomenul de subdepăşire.
Observaţie: Dezavantajele acestei metode de implementare constau în aceea că operaţia
de inserare, respectiv suprimare, în interiorul listei necesită deplasări de elemente şi deci
operaţiile sunt ineficiente.
Temă: Scrieţi un program care descrie toate operaţiile unei liste liniare implementată prin tipul
tablou, ca mai sus, punând în evidenţă şi toate situaţiile de excepţie.
Listele înlănţuite sunt cele mai frecvent utilizate structuri de date după tablouri. Ele oferă
un mecanism extrem de eficient care poate fi utilizat în multe tipuri de baze de date. Listele pot
înlocui structuri de bază pentru implementarea altor structuri cum sunt stivele sau cozile. De fapt
se pot utiliza listele înlănţuite aproape peste tot unde se utilizează tablourile (cu excepţia cazului
în care avem frecvent nevoie de accesul la elementele individuale ale listei prin intermediul unui
indice).
Listele înlănţuite nu reprezintă o soluţie universală pentru toate problemele legate de
memorarea datelor, dar sunt surprinzător de eficiente şi conceptual mai simple decât alte
structuri binecunoscute, cum sunt arborii.
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:
in1 adr2 in2 adr3 inn nil
adrt
Se completează informaţiile pentru nodul creat –adresa acestuia va trebui să conţină
adresa nodului care trebuie să-i urmeze în listă:
5 adr2
adrt
Se modifică adresa nodului care precede nodul nou creat. Adresa trebuie să fie a nodului
nou creat:
5 adr2
adrt
Lista poate fi “privită” lista aşa cum am fost obişnuiţi:
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”.