Sunteți pe pagina 1din 40

Algoritmi si structuri de date

III. Liste liniare


1. Definitie. Operatii asupra listelor
2. Liste liniare particulare
3. Implementarea secventiala a listelor liniare
4. Implementarea inlantuita a listelor liniare

Intocmit pe baza: S. Barza, L. M. Morogan, Structuri de date, EFRM,


2007, Cap III, p. 42-71
1. Definitie. Operatii asupra listelor
Lista liniara – insiruire de elemente de acelasi tip.
Lista vida – lista care nu contine niciun element.
Daca lista nu e vida, atunci ea contine un prim element si un ultim element, nu
neaparat distincte.
Fiecare element, in afara de primul element al listei, are un predecesor; fiecare
element, in afara de ultimul element al listei, are un succesor.
A – multime de valori de acelasi tip.
H = {1, 2, …, n}
f : H -> A – lista liniara cu n elemente.
H = Φ => lista vida. Not.: f = null; first (null) = last (null) = λ
Daca f ≠ null: first (f) = f(1), last (f) = f (n).
pred(f(i)) = null, daca i = 1 succ(f(i)) = null, daca i = n
 
 f(i  1 ), daca i  1  f(i +1 ), daca i  n
Operatii asupra listelor: accesul la un element dat, inserarea unui element intr-o
pozitie data, eliminarea unui element din lista, combinarea a doua sau mai multe
liste pentru a obtine una singura, spargerea unei liste in doua sau mai multe
liste, copierea unei liste, ordonarea elementelor unei liste.
2. Liste liniare particulare
2.1. Stiva – lista liniara pentru care accesul se realizeaza doar la unul din capetele
listei, varful stivei. Elementul de la capatul opus – baza stivei.
Principiul de functionare: LIFO (Last In – First Out).
Overflow (depasire superioara) – intregul spatiu alocat stivei este ocupat si se
incearca adaugarea inca a unui element; operatia esueaza.
Underflow (depasire inferioara) – stiva este vida si se incearca eliminarea unui
element; operatia esueaza.

2.2. Coada – lista liniara pentru care accesul se face pe la unul din capete (varful
cozii), iar depunerea unui element pe la capatul opus (baza cozii).
Principiul de functionare: FIFO (First In – First Out).

2.3. Coada completa – lista liniara in care depunerile si extragerile sunt permise la
oricare din capetele listei (capatul stang, capatul drept).
Daca la unul dintre capetele cozii complete nu sunt permise operatii de depunere
(extragere) = coada completa restrictionata la intrare (iesire) la acel capat.
2. Liste liniare particulare
2.4. Coada cu prioritati : f : H → A x P, unde A – multime de valori de acelasi tip,
H = {1, 2, …, n}, P = {1, 2, …, m}, f (k) = (v (k), p (k)), v (k) – valoarea
corespunzatoare elementului de pe pozitia k, p (k) – prioritatea elementului de
pe pozitia k.
Cu cat valoarea prioritatii unui element este mai mica, cu atat elementul este mai
prioritar. Implementarea standard presupune p (1) ≥ p (2) ≥ … ≥ p (n).
Varful cozii cu prioritati – pt extragere; baza cozii cu prioritati – pt depunere.
Depunerea unui element:
• q, prioritatea elementului nou, nu apare in coada de prioritati:
• q mai mica decat oricare prioritate existenta => depunere la varf;
• q mai mare decat oricare prioritate existenta => depunere la baza;
• Celelalte cazuri: se determina k a.i. p (k ) > q > p (k + 1), si depunerea se
realizeaza intre elementele k si k + 1.
• q, prioritatea elementului nou, apare in coada de prioritati:
• p (1) = q, depunerea se realizeaza la baza cozii cu prioritati;
• Se determina cea mai mica valoare k pt care p (k) = q si depunerea se
face intre elementele k – 1 si k.
3. Implementarea secventiala a listelor liniare
= elementele listei sunt memorate unul dupa altul in ordinea in care apar in lista, in
locatii de memorie consecutive. (realizare practica: vectori)

3.1. Stiva secventiala


Stiva S se implementeaza cu vectorul A de m elemente.
V = varful stivei = pointerul stivei
Initializare stiva (S = Φ): V = 0
Depunere element x (x => S):
daca V = m
atunci overflow
altfel V = V + 1; A(V) = x

Extragere in z a unui element (z <= S):


daca V = 0
atunci underflow
altfel z = A(V); V = V - 1
3. Implementarea secventiala a listelor liniare
3.2. Coada secventiala
Coada C se implementeaza cu vectorul A de m elemente. Daca coada nu este vida,
intotdeauna unul din capete este A(1). P – pointerul cozii – catre celalalt capat
Initializare coada (C = Φ): P = 0
Implementare secventiala cu decalare unitara
Caz 1: A(1) – baza cozii; P – varful cozii
x => C: z <= C:
daca P = m daca P = 0
atunci underflow
atunci overflow
altfel z = A(P); P = P - 1
altfel
pt i = P, P-1, …, 1
A(i+1) = A(i)
P=P+1
A(1) = x
3. Implementarea secventiala a listelor liniare
3.2. Coada secventiala
Implementare secventiala cu decalare unitara
Caz 2: A(1) – varful cozii; P – baza cozii
x => C: z <= C:
daca P = m daca P = 0
atunci underflow
atunci overflow
altfel
altfel z = A(1)
P=P+1 pentru i=1,2,…P-1
A(P) = x A(i) = A(i + 1)
P=P-1

Implementare seventiala cu decalare multipla


– se aplica decalare multipla doar in cazul in care o depunere suplimentara ar
depasi spatiul alocat vectorului in care se stocheaza coada
- extragerea se face spre A(1); depunerea se face spre A(m)
- Initializarea cozii (C = Φ): B = V = 0
3. Implementarea secventiala a listelor liniare
3.2. Coada secventiala
Implementare seventiala cu decalare multipla
B – baza cozii; V – elementul de dinaintea celui din varful cozii

x => C: z <= C:
daca B = m daca B = V
atunci underflow
atunci daca V = 0
altfel
atunci overflow V = V + 1; z = A(V)
altfel
pentru i = V + 1, …, B
A(i – V) = A(i)
B = B – V; V = 0
B = B + 1; A(B) = x
3. Implementarea secventiala a listelor liniare
3.2. Coada secventiala
Implementare seventiala circulara
B – baza cozii; V – elementul de dinaintea celui din varful cozii
modulom: N → {1, 2, …, m}
modulom(k) = 1 + r, unde r – restul impartirii lui k la m
Initializarea cozii (C = Φ): B = V = m

x => C: z <= C:
daca V = modulom(B + 1) daca B = V
atunci underflow
atunci overflow
altfel
altfel V = modulom(V + 1);
B = modulom(B + 1) z = A(V)
A(B) = x
3. Implementarea secventiala a listelor liniare
3.3. Coada secventiala completa
D – coada completa; A – vector de m elemente; DL – capat stang; DR – capat drept
Implementare seventiala cu decalare unitara
A(1) = DL; P – pointerul cozii complete; initializare (D = Φ): P = 0
x => DL: x=> DR:
daca P = m daca P = m
atunci overflow
atunci overflow
altfel
altfel P = P + 1; A(P) = x
pentru i = P,…,1
A(i + 1) = A(i)
P = P + 1; A(1) = x
-------------------------------------------------------------------------------------------
z <= DL: z <= DR:
daca P = 0 daca P = 0
atunci underflow
atunci underflow
altfel
altfel z = A(P); P = P -1
z = A(1)
pentru i = 2,…,P
A(i - 1) = A(i)
P=P-1
3. Implementarea secventiala a listelor liniare
3.3. Coada secventiala completa
Implementare seventiala circulara
L - variabila pentru indicarea capatului stang DL; R - variabila pentru indicarea
capatului drept DR; initializare (D = Φ): L = R = m
x => DL: x=> DR:
daca R = modulom(L - 1) daca L = modulom(R + 1)
atunci overflow
atunci overflow
altfel
altfel R = modulom(R + 1)
A(L) = x A(R) = x
L = modulom(L - 1)

-------------------------------------------------------------------------------------------
z <= DL: z <= DR:
daca L = R daca L = R
atunci underflow
atunci underflow
altfel
altfel z = A(R)
L = modulom(L - 1) R = modulom(R - 1)
z = A(L)
3. Implementarea secventiala a listelor liniare
3.4. Coada secventiala cu prioritati
C – coada cu prioritati; baza = primul element; varful = ultimul element; initializare
(C = Φ): E = 0
Implementare cu doi vectori: V, P de dimensiune m; V(i) = valoarea elementului;
P(i) = prioritatea corespunzatoare valorii
(x,y) => C: z <= C:
daca E = m daca E = 0
atunci underflow
atunci overflow
altfel
altfel z = V(E)
P(E + 1) = -1; k = 1 E=E-1
pentru P(k) > y
-------------------------------------------------------------------------------------------
k=k+1
pentru i = E, …, k
V(i + 1) = V(i)
P(i + 1) = P(i)
E=E+1
V(k) = x; P(k) = y
3. Implementarea secventiala a listelor liniare
3.4. Coada secventiala cu prioritati
Implementare printr-un singur vector cu structura de articol
(x,y) => C: z <= C:
daca E = m daca E = 0
atunci underflow
atunci overflow
altfel
altfel z = A(E).V
A(E + 1).P = -1; k = 1 E=E-1
-------------------------------------------------------------------------------------------
pentru A(k).P > y
k=k+1
pentru i = E, …, k
A(i + 1) = A(i)
E=E+1
A(k).V = x; A(k).P = y
3. Implementarea secventiala a listelor liniare
3.5. Liste secventiale cu spatiu partajat
Mai multe structuri liniare partajeaza acelasi spatiu alocat. Restrictie: informatiile
structurilor sunt de acelasi tip.
Ex. Toate structurile implicate sunt stive.
A – vector cu m elemente. S1,…, Sn stive care impreuna nu pot avea simultan mai
mult de m elemente niciodata.
A(1) – baza primei stive nevide. Stivele sunt una in continuarea celeilalte.
V – vector cu n + 2 elemente pt memorarea varfurilor stivelor
S0 – stiva fictiva cu varful in A(0) (element fictiv)
V(i + 1) – varful stivei Si
Sn+1 – stiva fictiva
Initializare {Si = Φ}, i = 1,…,n:
pentru i = 1,…, n + 2
V(i)=0
3. Implementarea secventiala a listelor liniare
3.5. Liste secventiale cu spatiu partajat
x => Si
daca V(n + 2) = m
atunci overflow
altfel
pentru j = V(n + 2), …, V(i + 1) + 1
A(j + 1) = A(j)
pentru j = i + 1, …, n + 1
V(j + 1) = V(j + 1) + 1
A(V(i + 1) + 1) = x; V(i + 1) = V(i + 1) + 1
z <= Si
daca V(i) = V(i + 1)
atunci underflow
altfel
z = A(V(i + 1)); V(i + 1) = V(i + 1) – 1
pentru j = V(i + 1) + 2, …, V(n + 2)
A(j – 1) = A(j)
pentru j = i + 1, …, n + 1
V(j + 1) = V(j + 1) - 1
4. Implementarea inlantuita a listelor liniare
(v, l) = celula; v = valoarea, inf. utila; l = adresa urmatorului elem., inf. de legatura
l = Λ => celula reprezinta capat al listei (legatura nu face referire la o locatie de
memorie valida
Lista vida  adresa primului element = Λ.
Lista simplu inlantuita = inf. de legatura are o singura valoare
Lista dublu inlantuita = inf. de leg. are doua val.
Avantaj – alocare dinamica a datelor.

4.1. Implementare lista simplu inlantuita (v, l)


I. Sp. de mem. predef. pt. m celule cu adresele 1, 2, …, m
DISP – stiva in care sunt organizate celulele libere
• Initializare DISP:
Pt i = 1, …, m - 1
l(i) = i + 1
l(m) = Λ
DISP = 1
4. Implementarea inlantuita a listelor liniare
• Obtinerea unei celule din DISP: GETCELL(k)
daca DISP = Λ
atunci overflow
altfel k = DISP, DISP = l(DISP)

• Adaugarea la DISP a unei celule eliberate: FREECELL(k)


l(k) = DISP
DISP = k

II. In spatiul alocat dinamic in afara sp program


− Nu e necesara initializarea sp disponibil.
− GETCELL(k), FREECELL(k) – rutine ale limbajului de programare
− V = adresa primului element
• Initializare lista (L = Φ): V = Λ
4. Implementarea inlantuita a listelor liniare
• x => first (L)
GETCELL(k)
daca k = Λ
atunci overflow
altfel v(k) = x, l(k) = V, V = k

• x => last (L)


GETCELL(k)
daca k = Λ
atunci overflow
altfel
v(k) = x, l(k) = Λ
daca V = Λ
atunci V = k
altfel i = V
cat timp l(i) ≠ Λ
i = l(i)
l(i) = k
4. Implementarea inlantuita a listelor liniare
• x => nexti(L) – x se insereaza dupa al i-lea element din lista
j = V, n = 1
cat timp j ≠ Λ si n < i
j = l(j), n = n + 1
daca j = Λ
atunci overlist /* nr noduri lista < i; inserarea nu se poate face */
altfel
GETCELL (k)
daca k = Λ
atunci overflow
altfel
v(k) = x, l(k) = l(j), l(j) = k

• z <= first (L)


daca V = Λ
atunci underflow
altfel k = V, z = V(k), V = l(k), FREECELL(k)
4. Implementarea inlantuita a listelor liniare
• z <= last (L)
daca V = Λ
atunci underflow
altfel
u=Λ, i=V
cat timp l(i) ≠ Λ
u = i, i = l(i)
daca u = Λ
atunci V = Λ
altfel l(u) = Λ
z = v(i), FREECELL(i)

• z <= nexti(L): se stocheaza in z valoarea elementului din celula i, aceasta


eliberandu-se
j – adresa elementului t, u – adresa predecesorului
4. Implementarea inlantuita a listelor liniare
daca V = Λ
atunci underflow
altfel
u = Λ , j = V, t = 1
cat timp j ≠ Λ si t < i
u = j, j = l(j), t = t + 1
daca j = Λ
atunci overlist
altfel
daca u = Λ
atunci V = Λ
altfel l(u) = l(j)
z = v(j), FREECELL(j)
4. Implementarea inlantuita a listelor liniare
4.2. Stiva simplu inlantuita (inf, prev)
inf – informatia utila; prev – adresa nodului anterior; V – vf. stivei S
• Initializare (S = Φ): V = Λ
• x => S
GETCELL(a)
daca a = Λ
atunci overflow
altfel inf(a) = x, prev(a) = V, V = a
• z <= S
daca V = Λ
atunci underflow
altfel
a = V, V = prev (a)
z = inf (a), FREECELL(a)
4. Implementarea inlantuita a listelor liniare
4.3. Coada simplu inlantuita C - (inf, next)
inf – informatia utila; next – adresa nodului urmator de la V la B;
Depunere la baza B; extragere la varf V.
I. Sensul legaturilor: de la V la B
• Initializare (C = Φ): V = B = Λ
• x => C
GETCELL(a)
daca a = Λ
atunci overflow
altfel
inf(a) = x, next(a) = Λ
daca V = Λ
atunci V = a
altfel next(B) = a
B=a
4. Implementarea inlantuita a listelor liniare
• z <= C
daca V = Λ
atunci underflow
altfel
a = V, V = next(a)
daca V = Λ
atunci B = Λ
z = inf (a), FREECELL(a)

II. Sensul legaturilor: de la B la V (inf, succ)


Succ – adresa nodului succesor de la baza spre varf
• Initializare (C = Φ): B = Λ
• x => C
GETCELL(a)
daca a = Λ
atunci overflow
altfel inf(a) = x, succ(a) = B, B = a
4. Implementarea inlantuita a listelor liniare
• z <= C
daca B = Λ
atunci underflow
altfel
u = Λ, i = B
cat timp succ(i) ≠ Λ
u = i, i = succ(i)
daca u = Λ
atunci B = Λ
altfel succ(u) = Λ
z = inf(i), FREECELL(i)
4. Implementarea inlantuita a listelor liniare
III. Coada circulara simplu inlantuita C, (inf, succ), V
• Initializare (C = Φ): V = Λ
• x => C
GETCELL(a)
daca a = Λ
atunci overflow
altfel
inf(a) = x
daca V = Λ
atunci V = a, succ(a) = a
altfel succ(s) = succ(V), succ(V) = a
4. Implementarea inlantuita a listelor liniare
III. Coada circulara simplu inlantuita C, (inf, succ), V
• z <= C
daca V = Λ
atunci underflow
altfel
z = inf(V)
daca succ(V) = V
atunci FREECELL(V), V = Λ
altfel
a=V
cat timp succ(a) ≠ V
a = succ(a)
b=V
succ(a) = succ(b), V = a
FREECELL(b)
4. Implementarea inlantuita a listelor liniare
4.4. Implementarea listelor liniare dublu inlantuite
L (llink, inf, rlink)
I. Implementarea pe spatiu static de tip vector
+ stiva de noduri disponibile (ca la liste simplu inlantuite), legarea nodurilor
facandu-se doar pe unul din campurile de legatura (ex. llink)
II. Implementarea in spatiu dinamic
x => LEFT(L): depunere in capatul din stanga al listei
a. AL = adresa capatului stang al listei
GETCELL(a)
daca a = Λ
atunci overflow
altfel inf(a) = x, llink(a) = Λ, rlink(a) = AL
AL = a
4. Implementarea inlantuita a listelor liniare
b. AR = adresa capatului drept al listei
GETCELL(a)
daca a = Λ
atunci overflow
altfel inf(a) = x, llink(a) = Λ
daca AR = Λ
atunci rlink(a) = Λ, AR = a
altfel
p = AR
cat timp llink(p) <> Λ
p = llink(p)
llink(p) = a, rlink(a) = p
4. Implementarea inlantuita a listelor liniare
x => NEXT (t, L) introducerea dupa nodul cu adresa specificata prin t, in sensul de
la stanga la dreapta
GETCELL(a)
daca a = Λ
atunci overflow
altfel
inf(a) = x, llink(a) = t, rlink(a) = rlink(t), rlink(t) = a
p = rlink(a)
daca p ≠ Λ
atunci llink(p) = a
altfel AR = a /* daca se doreste memorarea AR */

x => RIGTH (L) analog x => LEFT (L)


4. Implementarea inlantuita a listelor liniare
z <= RIGTH (L)
a. Se cunoaste AR
daca AR = Λ
atunci underflow
altfel
a = AR, z = inf(a), AR = llink(a)
FREECELL(a)
daca AR ≠ Λ
atunci rlink(AR) = Λ
altfel AL = Λ /* daca se vrea memorarea AL */
4. Implementarea inlantuita a listelor liniare
z <= RIGTH (L)
b. Se cunoaste AL
daca AL = Λ
atunci underflow
altfel
p = AL
cat timp rlink(p) ≠ Λ
p = rlink(p)
q = llink(p)
z = inf(p), FREECELL(p)
daca q = Λ
atunci AL = Λ
altfel rlink(q) = Λ

z <= LEFT(L) - analog


4. Implementarea inlantuita a listelor liniare
Eliminarea nodului de la adresa t. Se cunosc AR si AL.
q = llink(t)
daca q = Λ
atunci AL = rlink(t)
altfel rlink(q) = rlink(t)
q = rlink(t)
daca q = Λ
atunci AR = llink(t)
altfel llink(q) = llink(t)
FREECELL (t)
4. Implementarea inlantuita a listelor liniare
4.5. Implementarea cozilor cu dubla inlantuire
C, B – baza = capat stang, V – varf = capat drept
C = Φ: B = V = Λ

x => C
GETCELL (a)
daca a = Λ
atunci overflow
altfel
inf(a) = x, llink(a) = Λ, rlink(a) = B, B = a
daca V = Λ
atunci V = B
4. Implementarea inlantuita a listelor liniare
4.5. Implementarea cozilor cu dubla inlantuire
z <= C
daca V = Λ
atunci underflow
altfel
a = V, z = inf(a)
V = llink(a), FREECELL(a)
daca V = Λ
atunci B = Λ
altfel rlink(V) = Λ
4. Implementarea inlantuita a listelor liniare
4.6. Implementarea cozilor circulare cu dubla inlantuire
C, B, trecerea spre varful cozii se face cu rlink. V este dat de legatura llink a lui B.
C = Φ: B = Λ
x => C
GETCELL(a)
daca a = Λ
atunci overflow
altfel
inf(a) = x
daca B = Λ
atunci B = a, rlink(a) = a, llink(a) = a
altfel
rlink(a) = B, llink(a) = llink(B)
llink(B) = a, rlink(llink(B)) = a
B=a
4. Implementarea inlantuita a listelor liniare
4.6. Implementarea cozilor circulare cu dubla inlantuire
z <= C
daca B = Λ
atunci underflow
altfel
a = llink(B), z = inf(a)
daca llink(a) = rlink(a)
atunci B = Λ
altfel rlink(llink(a)) = B, llink(B) = llink(a)
FREECELL(a)
4. Implementarea inlantuita a listelor liniare
4.7. Implementarea cozilor cu prioritati cu dubla inlantuire
CP, (llink, inf, prior, rlink), B, V
CP = Φ: B = V = Λ
z <= CP: ca la cozile simple
(x, p) => CP
GETCELL(a)
daca a = Λ
atunci overflow
altfel
inf(a) = x, prior(a) = p
daca B = Λ
atunci llink(a) = Λ, rlink(a) = Λ, B = a, V = a
altfel
daca p ≥ prior(B)
atunci rlink(a) = B, llink(a) = Λ, B = a
altfel
4. Implementarea inlantuita a listelor liniare
4.7. Implementarea cozilor cu prioritati cu dubla inlantuire
q=B
cat timp rlink(q) ≠ Λ si p < prior(q)
q = rlink(q)
daca rlink(q) = Λ si p < prior(q)
atunci
rlink(q) = a, llink(a) = V
rlink(a) = Λ, V = a
altfel
rlink(a) = q, llink(a) = llink(q)
rlink(llink(q)) = a, llink(q) = a

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