Sunteți pe pagina 1din 63

Structuri de date i algoritmi I

Complexitatea algoritmilor, Tablouri, Liste simple, Stive i Cozi

M.Craus

Autorul i cere scuze pentru eventualele erori din text

Partea I
Complexitatea algoritmilor

Capitolul

Aspecte generale

Teoria complexitii are ca obiect de studiu clasicarea problemelor, bazat pe timpul de execuie i
spaiul de lucru utilizat de algoritmi pentru soluionarea lor. Cnd se analizeaz algoritmi paraleli, se
poate lua n considerare i numrul de procesoare.
Dei teoria complexitii a fost dezvoltat pentru probleme de decizie, aceasta nu este o restricie
sever deoarece multe alte probleme pot  formulate n termeni de probleme de decizie. De exemplu, o
problem de optimizare poate  rezolvat prin punerea ntrebrii existenei unei soluii cu cel mult sau
cel puin o valoare specicat.

1.1

Msurarea complexitii

Complexitatea timpului de execuie a unui algoritm care rezolv o instan de dimensiune

a unei

=dimensiunea mainii) se noteaz cu T (p; n) = T (n).


Dac p = 1 atunci algoritmul este secvenial i T (n) = T (n) = T (n) msoar resursa timp solicitat

probleme, pe o masin cu

procesoare (p

de acesta.
Pentru algoritmii paraleli complexitatea spaiu nu este ntotdeauna relevant. Din acest motiv aceasta
este mai puin studiat la astfel de algoritmi.
O problem se numete

p.

dependent de dimensiunea mainii (PDD) dac n este o funcie de variabil


independent de dimensiunea mainii (PID). Un algoritm dependent

Altfel, problema se numete

de dimensiunea mainii este un algoritm ce rezolv o problem PDD. Altfel, algoritmul se numete
independent de dimensiunea mainii.

Factorul de ncrcare (L) al unei probleme este raportul n=p. Viteza Sp (n)
T1 (n)=Tp (n). Eciena (Ep (n)) unui algoritm paralel se denete

este raportul

a unui algoritm paralel


ca ind raportul dintre

vitez i numrul procesoarelor:

( ) = S (n)=p = T (n)=[p  T (n)]:


Pentru a aprecia comportarea asimtotic a funciei T (n) se utilizeaz urmtoarele noiuni:
Ep n

Fiind date dou funcii

pozitive de variabile

n,

se noteaz:

( ) = ff =(8)" > 0; 9[fp ; n (p)g  N ] a:i: (8)[(p > p ) ^ (n > n (p))] :


f (p; n) < "  g (p; n)g
Rezult c f este n o(g ) dac lim !1 (f =g ) = 0.
O(g ) = ff =9[fp ; n (p)g  N ^ c 2 R ] a:i: (8)[(p > p )) ^ (n > n (p))] :
f (p; n) < c  g (p; n)g
Deci f este n O (g ) dac funcia f =g este mrginit.
o g

Mitic Craus - Structuri de date i algoritmi

(g) = ff =9[fp ; n (p)g  N ^ fc ; c g  R ] a:i: (8)[(p > p ) ^ (n > n (p))] :


0 < c  g(p; n) < f (p; n) < c  g(p; n)g
Aceasta nseamn c f 2 (g ) dac f =g este o funcie strict pozitiv i mrginit.

(g) = ff =9[fp ; n (p)g  N ^ c 2 R ] a:i: (8)[(p > p ) ^ (n > n (p))] :


0 < c  g(p; n) < f (p; n)g
Rezult c f 2
(g ) dac f =g este mrginit inferior de o valoare strict pozitiv.
0

1.2

Clase de complexitate

Din punctul de vedere al calculului secvenial, sunt relevante trei clase:


Clasa

P, NP, Pspace.

: conine problemele solvabile n timp polinomial, ceea ce nseamn c pentru aceste prob-

leme exist algoritmi determiniti secveniali cu timpul de executie mrginit de un polinom de variabil

P sunt numite, n mod curent, bine soluionabile sau uoare.


NP : este clasa problemelor pentru care exista un algoritm sevenial nedeterminist cu timp de execuie

dimensiunea problemei. Problemele din

polinomial (echivalent : nu exist un algoritm secvenial determinist cu timp de execuie polinomial).

Pspace :

conine problemele care sunt solvabile utiliznd un spaiu polinomial, adic spaiul de lucru

este mrginit de un polinom de variabil dimensiunea problemei.

P  NP  Pspace. Se presupune c ambele incluziuni sunt proprii (stricte).


Pspace, neinteresant din punct de vedere al calculului secvenial, dar impentru calculul paralel este Polylogspace. Aici sunt incluse problemele rezolvabile n spaiu

Evident,

O alt clas inclus n


portant

polilogaritmic (spaiul de lucru este mrginit de un polinom de variabil log(dimensiunea problemei)).

P aparin lui Polylogspace, dar n general, se crede c P 6 Polylogspace. Se tie


Polylogspace 6= Pspace.
Remarcabile n Pspace i NP sunt problemele complete. Problemele Pspace-complete sunt generalizri ale tuturor celorlalte probleme din Pspace n termeni de transformri care necesit timp polinomial. Mai precis: o problem este Pspace-complet sub transformri de timp polinomial dac aparine
lui Pspace i oricare alt problem din Pspace este reductibil la ea prin transformri care necesit
timp polinomial. Urmeaz c dac o problem Pspace-complet ar apartine lui P, atunci Pspace =
P. Deoarece se crede c aceast egalitate nu este adevrat, este improbabil s existe un algoritm de
timp polinomial pentru o problem Pspace-complet. Problemele NP se denesc n mod asemntor,

Multe probleme din


totui c

rezultnd aceleai concluzii.

P are i ea problemele ei complete. Problemele P-complete sunt generalizri ale tuturor celorP, n termenii transformrilor care necesit spaiu de lucru logaritmic. Formal,
o problem este P-complet sub transformri spatiale logaritmice dac aparine clasei P i orice alt
problem din P este reductibil la ea prin transformri ce utilizeaz spaiu logaritmic. Dac o problem
P-complet ar aparine clasei Polylogspace, atunci ar  adevrat incluziunea P  Polylogspace.
Clasa

lalte probleme din clasa

Cum aceast incluziune se presupune a  fals, nu este de ateptat s existe un algoritm pentru o problem

P-complet care s utilizeze spaiu de lucru polilogaritmic.


1.3

Teze

Relaia ntre calculul secvenial i paralel este dat de teza calculului paralel (Chandra,

Kozen & Stockmeyer, 1981; Goldshlager, 1982): pentru orice funcie T (n), (n = dimensiunea problemei), clasa problemelor solvabile de o main cu paralelism nemrginit n timp T (n)O(1) (polinomial n T (n)) este egal
cu clasa problemelor solvabile de maini secveniale cu spaiul (T (n))O(1) .
Aceast tez este o teorem pentru multe dintre modelele relativ rezonabile. Astfel, clasa problemelor
solvabile n

()

T n

O (1)

timp de o main

PRAM

spaiu de lucru de o main Turing, dac

este egal cu clasa problemelor solvabile cu

( )  log n (Fortune & Wyllie, 1978).

T n

()

T n

O (1)

In consecin, clasa

Mitic Craus - Structuri de date i algoritmi

PRAM n timp paralel polinomial este egal cu clasa Pspace. De


Polylogspace este clasa problemelor solvabile de o main PRAM n timp paralel poliloga-

problemelor solvabile de o main


asemenea,
ritmic.
Problemele din

P\Polylogspace sunt solvabile n timp paralel polilogaritmic. Ele pot  considerate


P, n sensul c inuena dimensiunii problemei asupra timpului de rezolvare

cele mai uoare probleme din

a fost redus la minimum. O reducere ulterioar a timpului de soluionare la dimensiuni sublogaritmice


este, n general, imposibil. Una din raiunile acestei armaii este aceea c o main

(log n) timp pentru activarea a n procesoare.

Pe de alt parte, este improbabil ca problemele

PRAM

necesit

P-complete s admit soluii n timp polilogaritmic.

Dac o astfel de problem ar  rezolvabil n timp paralel polilogaritmic ar urma c aparine clasei

Polylogspace

i astfel ar  adevrat incluziunea

PPolylogspace.

Din acest motiv, nu este de

ateptat o soluie n timp paralel polilogaritmic. Orice metod de rezolvare pentru problemele grele din

P necesit probabil timp superlogaritmic i aceasta deoarece natura lor este probabil inerent secvenial.
Aceasta nu nseamn ns c paralelismul nu poate aduce creteri substaniale de vitez algoritmilor de
rezolvare.
In concluzie, clasa

probleme foarte uoare (very easy) care sunt rezolvabile


probleme mai puin uoare (not so easy), pentru care este improbabil

poate  partiionat n

n timp paralel polilogaritmic i


creterea vitezei prin paralelism.

Capitolul

Complexitatea algoritmilor secveniali

La evaluarea (estimarea) algoritmilor secveniali se pune n eviden necesarul de timp i de spaiu de


memorare. Atunci cnd se studiaz complexitatea spaiu se au n vedere resursele de memorie temporar
(suplimentar) utilizate de algoritm. Memoria rezervat reprezentrii instanei problemei nu intereseaz
n analiza complexitii spaiu.
Studierea complexitii presupune analiza urmtoarelor trei aspecte:
1. conguraia de date cea mai defavorabil (cazurile degenerate);
2. conguraia de date cea mai favorabil;
3. comportarea medie.
Comportarea medie presupune probabilitatea de apariie a diferitelor conguraii de date la intrare.
Aspectul 1 este cel mai studiat i este folosit, de obicei, pentru compararea algoritmilor secveniali.
Complexitatea unui algoritm secvenial se exprim de regul n limbajul ordinului

O.

Deniie:

Fie f : N ! N i g : N ! N dou funcii. Spunem c f 2 O(g ) i notm f = O(g ) dac i numai dac
exist o constant c 2 R+ i un numr n0 2 N astfel nct pentru 8n > n0 ; f (n) < c  g (n).
Observaie:

reprezint, de obicei, dimensiunea datelor de intrare iar

( ) timpul de lucru al algo-

f n

ritmului exprimat n pai.


Lem:

Dac f este o funcie polinomial de grad k , de forma: f (n) = ak  nk + ak


a1  n + a0 , atunci f = O(nk ).

n

+  +

Fcndu-se majorari n membrul drept, obinem rezultatul de mai sus:

( )  ja j  n + ja j  n +    + ja j  n + ja j < n  (ja j + ja j + ja j) < n  c


pentru 8n > 1 ) f (n) < c  n , cu n = 1.
Concluzie: f = O(n ), i ordinul O exprim viteza de variaie a funciei, funcie de argument.
f n

Exemplul 1:
Fie

A,

Cutarea secvenial.

de ordin

n,

un tablou unimesional. Se cere s se determine dac elementul

elementele tabloului.

SECV_SEARCH(A,n,b)

i 1;
WHILE ( A[i]<>b and i<n ) DO
i i+1
END_WHILE
5

se a printre

Mitic Craus - Structuri de date i algoritmi

IF (A[i]=b) THEN
RETURN(i); // b a fost gsit pe poziia i n tabloul A
ELSE
RETURN(0); // b nu a fost gsit n tabloul A
END_IF

END

Complexitatea timp:

Cazul cel mai defavorabil:


tat de tabloul

situaia n care elementul

A.

nu aparine mulimii secvenializate implemen-

Dac notm cu T (n) timpul de execuie n pai al acestui algoritm, atunci T (n) = 1+2n 1+1 = 2n +
1 = numrul de atribuiri i comparaii. O expresie logic este asimilat n cele ce urmeaz cu o comparaie
(ex. A[I]<>b and i<=n ) . Putem spune c T (n) = O (n) deoarece T (n) o funcie polinomial de gradul
I. Conteaz deci doar gradul polinomului, nu polinomul n ansamblu i nici coecientul termenului de
grad maxim , iar la numrarea pailor concentrarea se focalizeaz asupra numrului buclelor, nu asupra
pailor din interiorul buclei.

O secven de pai de dimensiune constant nu este relevant deoarece

aceasta poate diferi de la algoritm la algoritm funcie de gradul de detaliere ( ex.

inteschimbare(a,b);).
Comportarea medie: Se poate

aux a; a b; b aux

versus

poziia

( )=

considera c probabilitatea ca elementul

sau n afara acestuia este aceai

(3 + 5 + : : : + 2n 1 + 2n + 1 + 2 + 1) =
+ < n + 3 = O(n)

1
n+1
2(n+1)(n+2)
2(n+1)

T n

n+1

Observtie:

Cazul n care elementul

cazul n care elementul


elementul

se a pe poziia

nu se a n tabloul

A.

s se ae n tabloul

pe

= 1; : : : ; n sau i > n. n aceste condiii


f2[1 + 2 + : : : + n + (n + 1)] + n 1g =

1
pentru ecare i
n+1
1
n
n+1

n tabloul

se rezov n timp egal cu

Aceasta deorece ultimul test analizeaz situaia n care

este n una din aceste dou situaii.

Complexitatea spaiu:
Memoria auxiliar utilizat de algoritmul SECV_SEARCH este cea necesar reprezentrii valorilor
lui

deci un numar x de locaii.

Rezult c dimensiunea spaiului de memorie suplimentar este o

constant deci un polinom de grad zero. Astfel complexitatea spaiu este

(1).

n continuare va  analizat doar complexitatea timp pe cazul cel mai defavorabil. Complexitate timp
mediu i complexitatea spaiu vor  calculate doar pentru algoritmi relevani n acest sens.

Exemplul 2: Calcularea maximului unui ir.


MAX_SIR (A,n)
max
A[1];
FOR i = 2 to n DO
IF A[i]) > max THEN
max
A[i];
END_IF
END_FOR
RETURN (max)

END

Cazul cel mai defavorabil:

situaia n care vectorul este ordonat cresctor (pentru c de ecare dat

se face i comparaie i atribuire).


n acest caz numrul de atribuiri i comparaii =

Exemplul 3:

( ) = 1 + 2(n 1).

T n

Sortarea prin inserare (Insertion Sort)

Algoritmul INSERTION SORT consider c n pasul


elementul

Inserarea elementului

k,

elementele

[1  k 1] sunt sortate, iar


A[1  k ] s e sortate.

va  inserat, astfel nct, dupa aceast inserare, primele elemente

n secventa

[1  k 1] presupune:

memorarea elementului ntr-o varibil temporar;

Mitic Craus - Structuri de date i algoritmi

deplasarea tuturor elementelor din vectorul

[1 k 1] care sunt mai mari dect A[k], cu o poziie

la dreapta (aceasta presupune o parcurgere de la dreapta la stnga);

plasarea lui

[ ] n locul ultimului element deplasat.

Ak

INSERTION_SORT (A,n)

FOR k = 2 to n DO
temp
A[k];
i
k-1;
WHILE (i >=1 and A[i] > temp) DO
A[i+1]
A[i];
i
i-1;
END_WHILE
A[i+1]
temp;
END_FOR

END

Cazul cel mai defavorabil:

situaia n care deplasarea (la dreapta cu o poziie n vederea inserrii) se

face pn la nceputul vectorului, adic irul este ordonat descresctor.


Exprimarea timpului de lucru:

( ) = 3  (n 1) + 3  (1 + 2 + 3 +    + n 1) = 3(n 1) + 3n(n 1)=2


Rezult complexitatea: T (n) = O (n )  funcie polinomial de gradul II.
T n

Exemplul 4:

nmulirea a dou matrici.

PROD_MAT (A,B,C,n)

FOR i = 1 to n DO
FOR j = 1 to n DO
C[i,j]
0;
FOR k = 1 gets n DO
C[i,j]
C[i,j] + A[i,k] * B[k,j];
END_FOR
END_FOR
END_FOR

END

Rezult complexitatea

Exemplul 5:
Fie

A,

( ).

O n3

Cutarea binar (Binary Search).

de ordin

n,

un vector ordonat cresctor. Se cere s se determine dac o valoare

elementele vectorului. Limita inferioar se numete


virtual al vectorului,

mid

low,

limita superioar se numete

(de la middle).

BINARY_SEARCH (A,n,b)

low
1;
high
n;
WHILE (low =< high) DO
mid
(low + high)/2; // partea ntreag
IF (A[mid]=b) THEN
RETURN (mid);
ELSE
IF A[mid]>b THEN
high mid-1; // restrng cutarea la partea stng
ELSE
low
mid+1; // restrng cutarea la dreapta

se a printre

high,

iar mijlocul

Mitic Craus - Structuri de date i algoritmi

END_IF
END_IF
END_WHILE
RETURN(0)

END

Calculul complexitii algoritmului const n determinarea numrului de ori pentru care se execut
bucla while.
Se observ c, la ecare trecere, dimensiunea zonei cutate se njumtete.
secvenial, cazul cel mai defavorabil este situaia n care vectorul
Pentru simplitate, se consider
printr-o majorare,

( )  log n + 1.

T n

=2

unde

Deci complexitatea timp a acestui algoritm este

log x = log b log


a

log

Ca i la cutarea

nu conine valoarea cutat.

este numrul de njumtiri. Rezult

= log

(log n). Baza logaritmului se poate ignora deoarece:


O(log n), adic o funcie logaritmic.
2

este o constant, deci rmne

Proprieti ale ordinului de complexitate O :


1)

Fie f; g : N

! N.

Dac f

= O(g) atunci k  f = O(g) i f = O(k  g); 8k 2 R

Aceast propriatate este util n majorarile care apar necesare atunci cnd se estimeaz dimensiunea
resursei timp sau spaiu utilizat de un algoritm.
2)

Fie f; g; h : N

! N i f = O(g); g = O(h): Rezult f = O(h)

Aceast proprietate poate  folosit la ncadrarea unui algoritm n alt clas de complexitate, pentru
a prelua rezultate cunoscute relative la clasa n care a fost inclus.

Fie f ; f ; g ; g : N ! N .
 f = O(g  g )

3)
i

f1

i f1

= O(g ); f = O(g ) Rezult f + f = O(g + g )


1

Proprietatea 3) permite ca, atunci cnd dou bucle (de complexiti diferite) sunt succesive, complexitatea total s se obin prin adunarea complexitilor buclelor. Dac buclele sunt imbricate, complexitatea total se obine prin nmulirea complexitilor buclelor.
Aceast proprietate este de asemenea util atunci cnd algoritmul conine apeluri de funcii ale cror
complexitate este cunoscut.
Mai mult chiar, proprietatea 3) poate  folosit la schimbarea unitii de masur a instruciunilor unui
algoritmi. Astfel, dac un algoritm conine instruciuni nedetaliate, atunci complexitatea algoritmului
rezultat prin detaliere se poate obine prin inmulirii complexitti calculate n ipoteza c o instruciune
nedetaliat solicia

(1) resurse, cu complexitatea instruciunilor nedetaliate.

Teorem:

Fie dou constante c > 0; a > 1. Dac f : N


atunci (f (n))c = O(af (n) ).
x
lim
!1 a

! N este o funcie monoton strict cresctoare,

Demonstraia se bazeaz pe limita

ntre ordinul funciilor polinomiale i cel al funciilor exponeniale exist relaia:

( )  O(a ).

O nc

Au loc urmtoarele incluziuni:

(1)  O(log n)  O(log n)  O(n)  O(n )    


 O(n )  O(2 )
2

k+1

Pentru calculul complexitii se va ncerca ncadrarea n clasa cea mai mic de complexitate din acest
ir:

O
O
O
O
O
O

(1)
(log n)
(log n)
(n)
(n )
(n )
k

k+1

 clasa algoritmilor constani;


 clasa algoritmilor logaritmici;
 clasa algoritmilor polilogaritmici;
 clasa algoritmilor liniari;
 clasa algoritmilor patratici;
 clasa algoritmilor polinomiali;

Mitic Craus - Structuri de date i algoritmi


O

(2 )
n

 clasa algoritmilor exponentiali.

Tehnici de calcul al complexitii


Sume utile:

= n(n2+ 1) ) O(n )

i=1

X
n

i2

i=1

= n(n + 1) 6 (2n + 1) ) O(n )


3

= n (n4+ 1) ) O(n )

i3

i=1

X
n

P
n

Sa calculm, de exemplu, suma:


Se noteaz:

i=1

( ) = P i2
n

G n

2 =2

n+1

2

( ) = 2  G(n)
n+1

i=0

i=1

( )=

G n

=n2

2+

G n

X
n

X
n

2i  2

i=1

X
n

P
n

Prin aceeai tehnic se calculeaz suma:

i=1

(i 1 i)  2 = n  2

i=1

2 =

i=1

n+1

X
n

i=1
n

X
i=1

(n 1)  2

2

i+1

X
n

2 =
i

i=1

2 = (n 1)  2
i

n+1

+2

Mitic Craus - Structuri de date i algoritmi


|

10

Partea II
Structuri de date

11

Capitolul

Aspecte generale

3.1

Tipuri i structuri de date

Deniie.

O structur de

date este

o colecie organizat

de date peste care este denit un

set de operaii.

Organizarea coleciei presupune existena unei topologii relaionale ntre elementele coleciei.
Att

structura

ct i

tip de date este dat de

tipul de date se refer la o colecie de date. Diferena dintre o structur i un


compoziia coleciei i de sistemul relaional existent ntre elementele coleciei

referite.
Colecia referit de un tip de date este omogen n timp ce colecia referit de o structur poate  i
neomogen.

C referit de un tip de date este denit cel mult o relaie de ordine "".

Peste colecia

Structura

presupune un sistem relaional care n varianta cea mai simpl poate induce o relaie de ordine. n general
sistemul relaional
un alt element

e2

R este o submulime a produsului cartezian C  C . Un element e este n relaie cu


(e ; e ) 2 R. Aceasta nseamn c relaia de ordine este n general o component
1

dac

sau o consecin a sistemului relaional.


Deci, denitorii pentru un tip de date sunt atributele de valoare ale elementelor i nu relaiile dintre
ele. n cazul structurilor de date determinante sunt relaiile.

Tipul de date presupune uzual un model de reprezentare a elementelor mulimii la care se refer tipul.
intreg denete o submulime a mulimii numerelor ntregi, reprezentate pe 2 octei

De exemplu, tipul

n cod complementar peste care sunt denite operaiile : +, :, *, /, operaii la nivel de bii (not, si,
i structura presupune un model de reprezentare (implementare) a
datelor coleciei dar n plus aceasta presupune i un model de reprezentare (implementare) a sistemului
relaional. Focalizarea la tip se face pe reprezentarea datelor n timp ce la structur n centrul ateniei

sau, sau exclusiv, deplasari), etc.

este reprezentarea sistemului relaional.

nu intereseaz reprezentarea,
abstracte.

Dac pentru un tip sau structur de date

tipul sau structura

de date se numesc

ci doar operaiile acceptate

Un tip poate ncorpora o structur n sensul c elementele tipului pot  structuri. Astfel de

structurate.
Operaiile denite

tipuri

se

numesc

pe colecia referit de un tip de date sunt dependente de compoziia mulimii i

reprezentarea elementelor acesteia. Astfel la tipul ntreg operaiile sunt caracteristice numerelor ntregi
reprezentate n cod complementar. Pentru tipul ntreg abstract operaiile sunt cele denite pe mulimea
numerelor ntregi.

Dac tipul este structurat operaiile caracteristice tipului sunt dependente de cele

denite pe structura care este la baza tipului. Colecia referit de un tip de date este nit i are caracter
static n sensul ca este nemodicabil n timp, aspect ce caracterizeaz noiunea matematic de mulime.

Operaiile denite pe colecia referit de o structur deriv din compoziia coleciei, din sistemul
relaional denit peste colecie i caracterul static sau dinamic al acesteia. Corespunztor caracterului
static sau dinamic al coleciei de date avem dou tipuri de structuri: statice i dinamice. Pentru ecare

12

Mitic Craus - Structuri de date i algoritmi

13

tip de structur operaiile sunt specice.


Structurile statice se refer la colecii nite, nemodicabile n timp. Astfel de colecii pot  omogene
sau neomogene aspect ce lipsete noiunii de tip de date.

Sistemul relaional are un rol secundar n

determinarea operaiile denite pe structurle statice. Acestea sunt dominant dependente de compoziia
coleciei referite de structur.
Structurile dinamice colecii potenial innite, modicabile n timp. Operaiile caracteristice structurilor dinamice sunt dependente de sistemul relaional denit peste colecie. Urmatoarele operaii sunt
tipice structurilor dinamice:

explorarea

coleciei n scopul determinrii

apartenenei sau ne-apartenenei

unui element anume la

colecie;




inseria, tergerea sau modicarea

unui element din colecie;

identicarea predecesorului sau succesorului direct

al unui element conform cu sistemul relaional

R denit peste colecie: aceasta nseamn c dac perechea de elemente (e ; e ) 2 R atunci e este
predecesorul direct a lui e ( e = pred(e ) ) iar e este succesorul direct al lui e ( e = succ(e ) );
1

identicarea elementului minim sau maxim

conform cu relaia de ordine total denit peste

colecie, dac o asemenea relaie de ordine exist;

3.2

Structuri ordonate i structuri nlnuite

structur ordonat (implicit) presupune o ordine a poziiilor


structur sucesorul unui element aat pe o poziie i este elementul

elementelor coleciei.

ntr-o asfel de

situat pe poziia urmtoare. Sistemul

relaional are la baz arhitectura poziiilor, ind astfel exterior elementelor coleciei referite de structur.
Astfel, relaiile ntre elementele coleciei sunt implicite, motiv pentru care astfel de structuri se mai
numesc i structuri implicite. Implementarea unei astfel structuri presupune alocarea n prealabil a unei
grupri de locaii succesive de memorie sucient de mare i de dimensiune nemodicabil, zon n care
va  incrcat i procesat structura. Aceasta limiteaz potenialul unei astfel de structuri.
O

structur nlnuit (explicit)

este caracterizat prin includere informaiilor necesare calculrii

succesorului i/sau predecesorului unui element n compoziia elementului.


sorul unui element

Succesorul i/sau predece-

este identicat prin intermediul informaiilor de nlnuire coninute de elementul

respectiv. Astfel, sistemul relaional al elementelor este nregistrat n structura acestora deci este explicit.

Capitolul

Tablouri

4.1

Aspecte generale

Deniie. Tabloul ca structur abstract este o colecie omogen de date n care ecare element poate
 identicat pe baza unui index, colecia asigurnd acces direct i timp de acces constant pentru ecare
element. Tabloul este deci o structur ordonat.
Tabloul este o structur static n sensul imposibilitii modicrii n timp a dimensiunilor acestuia.
Valorile coninute ntr-un tablou pot  modicate n timp ceea ce nseamn ns c doar atributele de
valoare ale elementelor tabloului se schimb n timp i nu elementele lui.
Prin implementarea (reprezentarea) unui tablou se nelege plasarea valorilor asociate elementelor ce
compun tabloul n locaii succesive de memorie:

Locaiile de memorie pot  numerotate, permind accesarea direct a oricrui element. Numerele
asociate astfel locaiilor de memorie se numesc indecii tabloului.

Un tablou poate  vzut ca o mulime de perechi


numit

V alori.

< index; valoare > unde index aparine la o mulime

Indeci peste care este denit o relaie de ordine total iar valoare aparine la o mulime numit

A = (1; 3; 2; 5) poate  gndit ca ind mulimea de perechi f< 1; 1 >


3 2 >; < 4; 5 >g. Mulime indecilor este n acest caz I = (1; 2; 3; 4).
Dac tabloul este k -dimensional, k  2, atunci indexul este un k -uplu format din indecii asociai
Exemplu: Tabloul unimensional

23

; < ; >; < ;


dimensiunilor.

A  poate  implementat ca o mulime f< (i; j ); a > = 0  i 


1; 0  j  n 1g unde (i; j )  (k; l) , m  i + j  m  k + l. Mulimea indecilor este n acest caz
f(0; 0); (0; 1); : : : ; (0; m 1); (1; 0); (1; 1); : : : ; (1; m 1); : : : ; (n 1; 0); (n 1; 1); : : : ; (n 1; m 1)g.
Astfel un tablou bidimensional

Observaie.

ij

Acest tip de indexare este specic limbajului C.

2
3
1 3 5
4 2 10 12 5

Exemplu: Tabloul bidimensional

5 4 3
poate  gndit ca ind mulimea de perechif< (0; 0); 1 >; < (0; 1); 3 >; < (0; 2); 5 >; < (1; 0); 2 >; <
(1; 1); 10 >; < (1; 2); 12 >; < (2; 0); 5 >; < (2; 1); 4 >; < (2; 2); 3 >g
Generaliznd, un tablou multidimensional A 1  2   m poate  implementat ca o mulime f<
(i ; i ; : : : ; i ); a 1 2 m > = 0  i  n 1; k = 1; 2; : : : ; mg unde (i ; i ; : : : ; i )  (j ; j ; : : : ; j ) ,
n

i ;i ;:::;i

:::

14

Mitic Craus - Structuri de date i algoritmi

    +  
+ + 
+

 +:::+n i

n2 n3 : : : nm i1 n3 n4 : : : nm i2
j2 : : : nm jm 1 jm

Abordarea tablourilor ca mulimi de perechi

15

+i  n n :::n j +n n :::n 

< index; valoare >

este util n procesare matricilor

rare unde majoritatea elementelor sunt 0. Elementele cu valoarea 0 nu vor mai  reprezentate n memorie
din motive de utilizare ecient a acestei resurse. Trebuie precizat ns c n aceste condiii tablourile
devin structuri dinamice nlanuite. Elementul de tablou nu va mai  atomic ci va include n compoziia
sa

indexul i informaiile de nlanuire.

n concluzie tablourile pot  abordate ca structuri statice sau dinamice.

4.2

Exerciii

1. O seciune a unui tablou unidimensional (vector)

A1n

este o secven

ai ; ai+1 ; :::; aj ; i <

= j . Suma

unei seciuni este denit ca ind suma elementelor sale. Se presupune c elementele vectorului

sunt numere ntregi negative. S se scrie un algoritm care calculeaz seciunea de sum minim.
2. Se consider un tablou bidimensional

cu elemente de tip ntreg i cu proprietatea c elementele

ecrei linii i ecrei coloane sunt ordonate cresctor. Se tie c elementul


mentele tabloului. S se scrie un algoritm care s determine
exist mai multe asfel de poziii pe care apare

x,

i0 ; j0

astfel nct

apare printre ele-

Ai0 ;j0

=x.

Dac

atunci algoritmul va determina una dintre ele (nu

are importan care); se impune ns ca numrul de operaii s e minim.


3. S se scrie o funcie C/C++ care s proceseze elementele unei matrice ptratice de dimensiune
impar, n ordinea parcurgerii acesteia n spiral, ncepnd cu colul stnga-jos.
Exemplu: Pentru matricea

ordinea parcurgerii este

2
4

a11
a21
a31

a12
a22
a32

a13
a23
a33

3
5

a31 a32 a33 a23 a13 a12 a11 a21 a22

4. S se scrie o funcie C/C++ care rotete cu

90 ,
o

n sens invers trigonometric (sensul acelor de

ceasornic), o matrice ptratic de dimensiune impar.

Drept centru de rotaie se va considera

elementul din mijloc. Este interzis utilizarea de matrici suplimentare.

2
4

Exemplu: Dac

atunci

rotit cu

90

este:

2
4

a11
a21
a31

a12
a22
a32

a13
a23
a33

a31
a32
a33

a21
a22
a23

a11
a12
a13

3
5
3
5

Capitolul

Liste simple

5.1

Aspecte generale

C ; R) n care colecia C este omogen iar relaia R

Deniie. O list simpl este o structur dinamic (


are urmtoarele proprieti:
1. este asimetric:

8e ; e 2 C ; e 6= e
1

2. exist dou elemente speciale




3.

2 i

(e ; e ) 2 R ) (e ; e ) 2= R;
1

(capul i ultimul element al listei)

pentru care:

(ultimul; e) 2 R atunci e = capul;


dac (e; capul ) 2 R atunci e = ultimul ;
inchiderea tranzitiv a relaiei R n f(ultimul; capul )g este o relaie de ordine total strict peste
dac

mulimea elementelor.
O consecina a propriettii

2 este aceea c ultimul element al listei are cel mult un succesor direct

(capul listei) i capul are cel mult un predecesor direct (ultimul element).
Din proprietatea

3 rezult c ecare element,

diferit de capul i ultimul element al listei, are un

predecesor direct i numai unul plus un succesor direct i numai unul.

L secvenializarea coleciei C conform cu relaia de ordine dat de nchiderea


R n f(ultimul; capul)g atunci L = (e ; e ; : : : ; e ); capul = e ; ultimul = e ) i R n
f(ultimul; capul)g = f(e ; e ); (e ; e ) : : : (e ; e )g = f(e ; e )=i = 1; 2; : : : ng unde n este dimensiunea
Dac se noteaz cu

tranzitiv a lui

i+1

coleciei.
Colecia de elemente care compun lista este modicabil n timp. Lista este deci o structur dinamic.
ntre elementele unei structuri de tip list

capul listei este singurul element accesibil direct din exterior.

Celelalte sunt n general accesibile indirect prin intermediul sistemului relaional care furnizeaz secvenial
informaii de identicare a elementelor n cadrul listei.

Accesul secvenial trebuie ineles n sensul c

informaiile de identicare a elementelor n cadrul listei se obin dup accesarea elementului predecesor
sau uneori succesor direct. Exist totui i situaii n care toate elementele unei liste sunt direct accesibile
(cazul listelor ordonate).

5.2

Operaii cu liste simple

Operaiile de baz care se pot face n cadrul unei liste simple sunt cele caracteristice structurilor dinamice:




consultare:

accesul la un element al listei;

parcurgere:

accesul sistematic la elementele listei;


16

Mitic Craus - Structuri de date i algoritmi






inserare:

inserarea unui element pe o anumit poziie n list;

tergere:

eliminarea unui element aat pe o anumit poziie n list;

17

modicare:

modicarea unui element al listei;

min/max:

identicarea elementului minim/maxim conform cu relaiile de ordine total denite

peste colecia referit de list, dac asemenea relaii de ordine exist;

Capitolul

Liste liniare

6.1

Aspecte generale

Deniie. O list liniar este o list simpl n care

(ultimul; capul) 2= R

Rezult urmtoarele:





capul listei nu are predecesor direct;


ultimul element nu are un succesor direct;

R este o ordine total strict peste mulimea elementelor.


Dac se noteaz cu L secvenializarea coleciei C conform cu relaia de ordine dat de nchiderea tranzitiv
a lui R atunci L = (e ; e ; : : : ; e ); capul = e ; ultimul = e i R = f(e ; e ); (e ; e ) : : : (e
; e )g
inchiderea tranzitiv a relaiei

6.2

Liste liniare ordonate

O list liniar ordonat este o structur ordonat de tip list liniar.

6.2.1 Operaii cu liste liniare ordonate


Consultarea, modicarea unui element, parcurgerea listei, identicarea elementului minim/maxim sunt
operaii care presupun explorarea parial sau total a listei, operaie care are la baz accesarea capului
listei (elementul de pe prima poziie) i apoi accesarea succesiv (secvenial) a elementelor aate pe
poziiile urmtoare pn cnd se obine rezulttul dorit.
Fie o list ordonat de forma:

a1

a2

...

ai

ai

ai+1

...

///////

Un prototip de explorare a unei astfel de liste este urmtorul:

i 0; // poziionare n faa listei


// ct timp nu este ndeplinit condiia impus de operaia de
// explorare i nu a fost depistat elementul fr succesor
WHILE not condiie(ai+1) and ai+1 6= ; DO
i i+1; // trece la elementul succesor
procesare ai ; // ex: afiarea elementului
END_WHILE
18

Mitic Craus - Structuri de date i algoritmi

19

Inserarea i tergerea unui element din list sunt operaii care necesit detaliere:

Inserarea
Inserarea unui element ntr-o list ordonat se face astfel:

elementele listei aate pe i dup poziia

n care se dorete nserarea sunt deplastate cu o poziie

spre stnga pentru a face astfel loc noului element. Conform cu gura urmtoare,
face nspre zona de memorie liber (cea haurat).

a1

a2

...

ai

a1

a2

...

ai

ai

ai+1
ai

...

ai+1

///////

...

///

in poziia astfel eliberat se plaseaz elementul

a1

a2

...

ai

ai

Algoritmul de inserare a unui element

ai+1
a

...

ce se dorete a  inserat n list

///

pe poziia

i:

j 0; // poziionare n faa listei


// ct timp nu a fost depistat elementul fr succesor
WHILE aj +1 6= ; DO
j j+1; // trece la elementul succesor
END_WHILE
//lista a fost parcurs ultimul element fiind accesibil
//
// ct timp nu a fost accesat elementul de pe poziia i
WHILE ji DO
aj +1
aj // deplasare la dreapta
j j-1; // trece la elementul predecesor
END_WHILE
ai
a // plasarea elementului a pe poziia i
O alta variant de inserare ar putea  aceea a plasrii unui element

j 0; // poziionare n faa listei


// ct timp nu a fost depistat element fr succesor
WHILE aj +1 6= ; DO
j j+1; // trece la elementul succesor
END_WHILE
//lista a fost parcurs ultimul element fiind accesibil
//
// ct timp nu a fost accesat elementul b
WHILE aj 6= b DO
aj +1
aj // deplasare la dreapta
j j-1; // trece la elementul predecesor
END_WHILE
aj +1
a // plasarea elementului a dup elementul b
tergerea
tergerea unui element dintr-o list ordonat se face n felul urmtor:

dup un element

b:

deplasarea

se

Mitic Craus - Structuri de date i algoritmi

elementele listei aate dup poziia

20

n care se dorete tergerea sunt deplastate cu o poziie spre

stnga.

a1

a2

...

ai

ai

a1

a2

...

ai

ai+1

ai+1
...

...

//////

//////////

Algoritmul de tergere unui element aat pe poziia i:

j i; // poziionarea pe elementul aflat pe poziia i - operaie


// posibila n cazul listelor ordonate
//
// ct timp nu a fost depistat elementul fr succesor
WHILE aj +1 6= ; DO
aj
aj +1 // deplasare la snga
j j+1; // trece la elementul sucesor
END_WHILE
// ultimul element a fost deplasat spre stnga cu o poziie
aj

// poziia veche a ultimului element conine acum

O alt variant de tergere ar putea  aceea a eliminrii unui element

a:

j 1; // poziionarea pe capul listei


// ct timp nu a fost depistat elementul a
WHILE aj 6= a DO
j j+1; // trece la elementul succesor
END_WHILE
// lista a fost parcurs pna la elementul a
//
// ct timp nu a fost depistat elementul fr succesor
WHILE aj +1 6= ; DO
aj
aj +1 // deplasare la snga
j j+1; // trece la elementul sucesor
END_WHILE
aj

// poziia veche a ultimului element conine acum

6.3

Liste liniare nlnuite

O list liniar nlnuit este o structur nlnuit de tip list liniar.

6.4

Liste liniare simplu nlnuite

O list liniar simplu nlnuit este caracterizat prin includere n compoziia elementului de list
numai a informaiilor necesare calculrii succesorului unui element.

Astfel, un element al unei liste

simplu nlnuite va avea urmtoarea structur:

(val; succ);
unde

val

este informaia de coninut (atributul de valoare) iar

succ

este informaia de nlnuire care

permite s identicm un elementului urmtor din list nlnuit. Pentru nlnuire se pot folosi i valori

Mitic Craus - Structuri de date i algoritmi

21

de tip adres de memorie sau de tip poziie. Informaia de nluire de tip poziie corespunde noiunii
de

index

iar cea de tip adres de memorie corespunde noiunii de

pointer.

Ambele noiuni sunt utilizate

n domeniul limbajelor de programare, indexul ind caracteristic tablourilor (alocate static) iar pointerul
alocrii dinamice acesta din urm ind o variabil care conine o adres de memorie.
O list poate  reprezentat astfel:

cap de lista

Adresa (indexul) capului de list este reinut ntr-o variabil special


o simbolizeaz o adres (poziie) invalid( ex:

l,

exterioar elementelor listei.

1 n cazul implementrii listei prin tehnici de alocare

static (tablouri) i NULL n C++ n cazul implementrii listei prin tehnici de alocare dinamic (care
utilizeaz pointeri).

Notaii






: adresa (poziia) unui element din list;

data(p) :

informaia de coninut a elementului de list indicat de

succ(p) :

informaia de nlnuire (legtura) memorat n elementul de list indicat de

q=get_sp() : alocarea unei zone de memorie n care


get_sp() va return adresa de nceput a zonei alocate;
free_sp(p) :

p;
p;

se poate memora un element din list :

eliberarea memoriei ocupat de elementul de list adresat de

p (zona devine refolosi-

bil).

Observaie.

Ultimele dou notaii se refer la cazul utilizrii tehnicilor de alocare dinamic pentru

implementarea listei.
Dac informaiile de nlnuire sunt materializate ca pointeri atunci n C++ un element de list va 
o astfel de structur:

struct Element f
Tip_Inf_Continut data;
Element* succ;
g;
Corespunztor cu notiile de mai sus vom avea:







tipul lui p  Element* p


data(p)  p!data
succ(p)  p!succ
q = get_sp()  q=new Element
free_sp(p  delete p.

Lista va  declarat astfel:

typedef Element* l; // l conine adresa capului listei


Fr a restrnge generalitatea, n continuare vom considera implemenatarea listelor prin tehnici de
alocare dinamic. n cazul alocrii statice dispar operaiile
nlocuiete cu cea de index.

get_sp i free_sp iar

noiunea de adres se

Mitic Craus - Structuri de date i algoritmi

22

6.4.1 Operaii cu liste liniare simplu nlnuite


Parcurgerea
Operaia de parcurgere a unei listei liniare simplu nlnuite se denete ca ind operaia de explorare
sistematic bazat pe accesul n colecia referit de list prin capul acesteia i accesul secvenial la celelalte
elemente, conform cu informaia de nlanuire

succ, n

scopul prelucrrii elementelor listei.

O parcurgere a listei presupune o prelucrare efectuat asupra ecrui element din list (aadar, nu o
funcie, ci o secven de instruciuni).
Fie

pointerul care adreseaz elementul curent accesibil.

p l;
WHILE p 6= o DO
prelucrare (data(p)) //ex: afiarea indormaiei de coninut
p succ(p) //trece la urmtorul
END_WHILE
Observaie. Consultarea, modicarea unui element al listei i identicarea elementului minim/maxim
sunt operaii care presupun parcurgerea parial sau total a listei.
Un prototip de parcugere parial poate  urmtoarea secven de pseudocod:

p l;
WHILE not condiie(p) and p 6= o DO
prelucrare (data(p)) //ex: afiarea indormaiei de coninut
p succ(p) //trece la urmtorul
END_WHILE
Inserarea

Exist trei situii tipice de inserare a unui element ntr-o list liniar simplu nlnuit:

 inserarea n fa listei (naintea primului element al listei);


 inserarea n interiorul listei;
 inserarea la sfritul listei (dup ultimul element al listei).

p.

Observaie.

Se presupune c elementul care urmeaz a  inserat are adresa coninut ntr-o variabil

n ultimele dou cazuri se presupune c elementul dup care urmeaz a se face inserarea are adresa

(pozitia) cunoscut (coninut ntr-o variabil

p).

a) Inserarea n fa listei (naintea primului element al listei)

q
q

1 : Prima atribuire:

succ(p)

2 : A doua atribuire:
q

p
Inserarea naintea primului element al listei se poate descrie astfel:

Mitic Craus - Structuri de date i algoritmi

23

succ(p)

2 :

--

1 :

Observaie.

Dac lista este vid,

are valoarea o (adresa capului listei) iar atribuirile de mai sus

rmn valabile:
c

1 :

succ(p)

2 :

b) Inserarea n interiorul listei

1  Prima atribuire:

1
q

p
Inserarea n interiorul listei se poate detalia astfel:

2  A doua atribuire:

succ(p)
succ(q)

succ(q)
p

Mitic Craus - Structuri de date i algoritmi

1 :

succ(p)

succ(q)

2 :

succ(q)

24

c) Inserarea la sfritul listei (dup ultimul element al listei)


Analog cu inserarea n interior:
1 :
2 :

succ(p)
succ(q)

succ(q)// succ(q)=o
p

tergerea
tergerea unui element dintr-o list liniar simplu nlnuit comporta urmtoarele situii:

 elementul ce se dorete a  ters este primul element al listei;


 elementul ce se dorete a  ters este situat n interiorul listei;
 elementul ce se dorete a  ters este ultimul element al listei.

Observaie.

n ultimele dou cazuri se presupune ca elementul dup care urmeaz a se face teregerea

are adresa (poziia) cunoscut (coninut ntr-o variabil

q).

a) tergerea primului element al listei


p

1 : Prima atribuire:

- T

-
TT 3

2 : A doua atribuire:

3 :

tergerea primului element al liste se poate descrie astfel:

Situaia iniial:
l
q

Situaii intermediare:

free_sp(p);

l
succ(l)

Mitic Craus - Structuri de date i algoritmi

25

p
q

1
l
q

1 :

2 :

succ(l)

3 :

free_sp(p); //elibereaz zona de memorie

p
q

Situaia nal:
p

b) tergerea unui element situat n interiorul listei


Variabila

va adresa elementul din faa celui care va  ters.


q

- SS -S

2 :

succ(p)

3 :

free_sp(q)

1 :

1 :

succ(p)

Situaia iniial:

succ(q)

Situaii intermediare:
q

succ(p)

Mitic Craus - Structuri de date i algoritmi


q

26

--

2 :

succ(p)

3 :

free_sp(q)

succ(q)

Situaia nal:
q

c) tergerea ultimului element al listei


tergerea ultimului element al listei se face la fel ca tergerea unui element situat n interiorul listei
Atunci cnd

conine adresa penultimului element dintr-o list liniar simplu nlnuit, atribuirile de

mai sus funcioneaz corect i terg ultimul element din list.


Nu se poate face tergerea elementului adresat de

fr parcurgerea listei de la capt.

6.4.2 Moduri de denire a poziiei elementului care urmeaz a  procesat


ntr-o list liniar simplu nlnuit
Operaia de inserare ntr-o list simplu nlnuit
Exist posibiliti diferite de a specica poziia n care se dorete inserrea unui element n list:

situaia n care poziia de inserat este dat prin numrul de ordine al elementului ce trebuie s e
inserat n list;

situaia n care poziia de inserat este dat prin valoarea elementului dup care sau nainte de care
se face inserarea;

situaia n care poziia de inserat poate  dat implicit prin informaia de coninut a elementului
de inserat - cazul listelor sortate.

n consecin inserarea unui element ntr-o list are algoritmi diferii, funcie de datele de nserare de
care se dispune.

Inserarea n faa unui element specicat prin informaia de coninut a elementului


Funcia nscrie un element n faa altui element dintr-o list:

INSERT(l,a,b)

// l - pointer la primul element


// a - informaia de coninut a elementului de inserat
// b - informaia de coninut a elementului n faa cruia
//
se insereaz
p get_sp();
data(p) a;
IF l=o THEN
eroare("Lista este vid");

Mitic Craus - Structuri de date i algoritmi

27

ELSE
IF data(l)=b THEN // inserare in faa primului element al listei
succ(p) l;
l p;
ELSE // inserare n interior
// caut n list elementul ce conine b
q l;
WHILE succ(q)6=o and data(succ(q))6=b DO
p succ(q);
END_WHILE
IF data(succ(q))6=b THEN
eroare("Elementul ce ar trebui s conin b nu se afl
n list");
ELSE // elementul ce conine b este curent accesibil
// inserare element ce conine a
succ(p) succ(q);
succ(q) p;
END_IF
END_IF
END_IF

END

Operaia de tergere dintr-o list liniar simplu nlnuit


in n acest caz exist posibiliti diferite de a specica poziia n care se dorete tergerea unui
element din list:

situaia n care poziia de ters este dat prin numrul de ordine al elementului ce trebuie s e
ters din list;

situaia n care poziia de ters este dat prin informaia de coninut a elementului care urmeaz a
 ters sau a elementului dup care sau nainte de care se face tergerea;

n consecin i tergerea unui element dintr-o list are algoritmi diferii, funcie de datele de tergere
de care se dispune.

tergerea elementului din faa unui element specicat prin informaia de coninut a elementului
Pseudocodul pentru o astfel de funcie de tergere poate  de forma:

DELETE(l,a)

// l - pointer la primul element


// a - informaia de coninut a elementului care trebuie ters
IF l=0 THEN
eroare ("Elementul nu se afl n list");
ELSE
IF data(l)=a THEN// tergerea primului element al listei
p l;
l succ(l);
free_sp(p);
ELSE
p l;
// caut n list elementul ce conine a
WHILE succ(p)6=o and data(succ(p))6= a DO
p succ(p);

Mitic Craus - Structuri de date i algoritmi

28

END_WHILE
IF succ(p)=o THEN
eroare ("Elementul ce ar trebui s conin a nu se afl
n list");
ELSE // tergere n interiorul listei sau a ultimului element
q succ(p);
succ(p) succ(q);
free_sp(q);
END_IF
END_IF
END_IF

END

6.4.3 Exerciii
1. Se citete, prin intermediul intrrii standard, un ir de numere ntregi.

S se plaseze numerele citite ntr-o list liniar simplu nlnuit, prin inserri repetate n faa
listei;





S se aeze lista creat;


Se citete un numr. S se determine dac acesta se a printre elementele listei create;
S se insereze un numr ntr-o poziie n list, numrul i poziia ind introduse prin inter-




mediul intrrii standard;


S se stearg un element din list, poziia de tergere ind dat la intrarea standard;
S se aeze elementul situat pe poziia k numart de la sfritul la nceputul listei, fr a
parcurge lista mai mult de o dat.

2. Fie

= (x ; x ; :::; x ) i Y = (y ; y ; :::; y ) dou liste liniare simplu nlnuite. Scriei un modul


1

C/C++ care:




s uneasc cele dou liste n una singur:

= (x ; x ; ::; x
1

s interclasese cele doua liste astfel:

 Z
 Z

= (x ; y ; x ; y ; :::; x
= (x ; y ; x ; y ; :::; x
1

; y1 ; y2 ; :::; ym

);

; ym ; xm+1 ; :::; xn dac m < n,


dac n <
m.
n ; yn ; yn+1 ; :::; ym

3. S se scrie funciile C/C++ care implementeaz urmtoarele operaii:





parcurgerea unei liste liniare simplu nluite n ambele sensuri (dus-intors) utiliznd O(1)
memorie suplimentar;
testarea situaiei n care o list liniar simplu nlnuita are bucle;
determinare mijlocul unei liste liniare simplu nlnuite (poziia elementului situat n mijlocul
listei).

6.5

Liste liniare dublu nlnuite

O list liniar dublu nlnuit este caracterizat prin includerea n compoziia elementului de list att
a informaiilor necesare calculrii succesorului ct i predecesorului elementului respectiv.
element

al unei liste liniare dublu nlnuite va avea urmtoarea structur:

(val; pred; succ);

Astfel, un

Mitic Craus - Structuri de date i algoritmi


unde

29

val este informaia de coninit al unui element al listei nlnuite, iar pred i succ sunt informaii

de nlnuire care permit identicarea elementului precedent i respectiv urmtor din lista liniar dublu
nlnuit.
Dac informaiile de nlnuire sunt materializate ca pointeri, o list liniar dublu nlnuit poate 
reprezentat astfel:

 -

q
q

 -

q
q

 -

cap de lista

Notaii

pred(p) :

informaia de nlnuire (legtura) ctre elementul urmtor, memorat n elementul de

list indicat de

succ(p) :

p,

informaia de nlnuire (legtura) ctre elementul precedent, memorat n elementul de

list indicat de

p,

n C/C++ un element de list va  o astfel de structur:

struct Element f
Tip_Inf_Continut data;
Element *pred,*succ;
g;
Corespunztor cu notiile de mai sus vom avea:




pred(p)  p!pred
succ(p)  p!succ

Lista va  declarat astfel:

typedef Element* l; // l conin adresa capului listei

6.5.1 Operaii cu liste liniare dublu nlnuite


Parcurgerea
Operaia de parcurgere a unei liste liniare dublu nlnuite se denete ca ind operaia de explorare
sistematic n scopul prelucrrii elementelor listei, bazat pe accesul n colecia referit de list prin capul
acesteia i accesul secvenial la celelalte elemente, conform cu informaiile de nlanuire
Fie

variabila care adreseaz elementul curent accesibil.

Parcurgere nainte

p l;
WHILE p6=o DO
prelucrare(data(p)); //ex: afiarea elementului
p succ(p) //trece la urmtorul
END_WHILE
Parcurgere nainte i napoi

p l;
WHILE p6=o DO

succ i pred.

Mitic Craus - Structuri de date i algoritmi

30

prelucrare(data(p)); //ex: afiarea elementului


p succ(p); //trece la urmtorul
END_WHILE
WHILE p6=o DO
prelucrare(data(p));
p pred(p); //trece la precedentul
END_WHILE

Observaie.

Consultarea, modicarea unui element al listei i identicarea elementului minim/maxim

sunt opertii care presupun parcurgerea parial sau total a listei.


Un prototip de parcugere parial poate  urmtoarea secven de pseudocod:

p l;
WHILE not condiie(p) and p6=o DO
prelucrare(data(p)); //ex: afiarea elementului
p succ(p); //trece la urmtorul
END_WHILE
Inserarea

Exist trei situaii tipice de inserare a unui element ntr-o list liniar dublu nlnuit:

 inserarea n faa primului element al listei;


 inserarea n interiorul listei;
 inserarea dup ultimul element al listei.
Se presupune c elementul care urmeaz a  inserat are adresa coninut ntr-o variabil

p.

ultimele dou cazuri se presupune ca elementul dup care urmeaz a se face teregerea are adresa (poziia)
cunoscut (coninut ntr-o variabil

q).

a) Inserarea n faa primului element al listei

-q

1 :
2 :
3 :
4 :

q
r

 -

q
q

 -

q
q

 -

pred(p) o
succ(p) l
pred(l) p
l p

b) Inserarea n interiorul listei


Se presupune ca elementul nainte sau dup care urmeaz a se face inserarea are adresa cunoscut
(coninut ntr-o variabil

q).

Inserarea naintea elementului adresat de q

Mitic Craus - Structuri de date i algoritmi

z
 3


4
1

2
q

JJ -q
q

1 :
2 :
3 :
4 :

31

q
q

 -

q
q

 -

succ(p) q
succ(pred(q)) p
pred(p) pred(q)
pred(q) p

Inserarea dup elementul adresat de q

1 :
3 :
4 :

 -:
q

2 :

q
q


J
-q

q
q

 -

q
q

 -

pred(p) q
pred(succ(q)) p
succ(p) succ(q)
succ(q) p

c) Inserarea dup ultimul element al listei


Se presupune c ultimul element al listei dup care urmeaz a se face inserarea are adresa cunoscut
(coninut ntr-o variabil

q).

Mitic Craus - Structuri de date i algoritmi


p

 -

 -

q
q

q
q

1 :
3 :

O
2

?
 -

2 :

32

pred(p) q;
succ(q)) p;
succ(p) o;

tergerea
tergerea unui element dintr-o list liniar dublu nlnuit comporta urmtoarele situii:

 elementul ce se dorete a  ters este capul listei;


 elementul ce se dorete a  ters este situat n interiorul listei
 elementul ce se dorete a  ters este ultimul element al listei.

Observaie.

n ultimul caz se presupune c elementul dup sau naintea cruia urmeaz a se face

teregerea are adresa cunoscut (coninut ntr-o variabil

p).

a) tergerea capului listei


p

-* AA H - A
4

c
q

 -

q
q

1 :
2 :
3 :
4 :

p l
l succ(l)
pred(l) o
free_sp(p)

b) tergerea unui element situat n interiorul listei


Variabila

adreseaz elementul din faa celui care va  ters.

 -

Mitic Craus - Structuri de date i algoritmi


q

 p

1 :
2 :
3 :
4 :

j
 - @@  -~
@
}

 - @@  -~
@
}

 -

j
~
 - @@  @
}
4

q
q

3 :

adreseaz elementul situat dup cel care va  ters.


q

4 :

 -

q pred(p);
succ(q) succ(p);
pred(succ(p)) q;
free_sp(p);

Variabila

2 :

1 :

 -

j
 -

3 :

4 :

 -

adreseaz elementul care va  ters.


q

2 :

q
q

q succ(p);
succ(p) succ(q);
pred(succ(q)) p;
free_sp(q);

Variabila

1 :

33

q pred(p);
pred(p) pred(q);
succ(pred(q)) p;
free_sp(q);

a) tergerea ultimului element al listei


Variabila

adreseaz penultimul element al listei.

Mitic Craus - Structuri de date i algoritmi

 -

q
q

 -

1 :

q
c

QQ - TT
T

q
c

 H - TT
T

2 :

free_sp(succ(p));
succ(p) o;

Variabila

adreseaz ultimul element al listei.

 -

q
q

 -

1 :

2 :

34

succ(pred(p)) o;
free_sp(p);

6.5.2 Moduri de denire a poziiei elementului care urmeaz a  procesat


ntr-o list liniar dublu nlnuit
Operaia de inserare ntr-o list liniar dublu nlnuit
i n cazul listelor liniare dublu nlnuite exist posibiliti diferite de a specica poziia n care
se dorete inserarea unui element n list.

Acestea sunt aceleai ca la listele liniare simplu nlnuite.

Algoritmii difer ns de cei din cazul listelor liniare simplu nlntuite. Aceast se datoreaz faptului c
operaia de inserare trebuie s actualizeze dou informaii de nlnuire (pred i

succ) i nu

una (succ).

De exemplu pentru inserarea n faa unui element specicat prin informaia de coninut, un prototip
de pseudocod este urmtorul:

INSERT(l,a,b)

// l - pointer la primul element


// a - informaia de coninut a elementului de inserat
// b - informaia de coninut a elementului n faa cruia
//
se insereaz
p get_sp();
data(p) a;
IF l=o THEN
eroare("Lista este vid");
ELSE
IF data(l)=b THEN // inserare in faa primului element al listei
pred(p) o;
succ(p) l;
l p;
ELSE // inserare n interior sau dup ultimul element
// caut n list elementul ce conine a
q l;
WHILE succ(q)6= o and data(succ(q))6= b DO
p succ(q);
END_WHILE

Mitic Craus - Structuri de date i algoritmi

35

IF data(succ(q))6=b THEN
eroare("Elementul ce ar trebui s conin b nu se afl
n list");
ELSE // elementul ce conine b este curent accesibil
// inserare element ce conine a
pred(p) q;
pred(succ(q)) p;
succ(p) succ(q);
succ(q) p;
END_IF
END_IF
END_IF

END

Operaia de tergere dintr-o list liniar dublu nlnuit


i n acest caz exist posibiliti diferite de a specica poziia n care se dorete tergerea unui element
din list:
Pentru tergerea elementului din faa unui element specicat prin informaia de coninut a elementului,
pseudocodul pentru o astfel de oepraie poate  de forma:

DELETE(l,a)

// l - pointer la primul element


// a - informaia de coninut a elementului care trebuie ters
IF l=0 THEN
eroare ("Elementul nu se afl n list");
ELSE
IF data(l)=a THEN// tergerea primului element al listei
p l;
l succ(l);
pred(l) o;
free_sp(p);
ELSE
p l;
// caut n list elementul ce conine a
WHILE succ(p)6= o and data(succ(p))6= a DO
p succ(p);
END_WHILE
IF succ(p)6=a THEN
eroare ("Elementul ce ar trebui s conin a nu se afl
n list");
ELSE // tergere n interiorul listei sau a ultimului element
q succ(p);
succ(p) succ(q);
pred(succ(q)) p;
free_sp(q);
END_IF
END_IF
END_IF

END

Mitic Craus - Structuri de date i algoritmi

36

6.5.3 Exerciii
1. Se citete, prin intermediul intrrii standard, un ir de numere ntregi.






2. Fie

S se plaseze numerele citite ntr-o list liniar dublu nlnuit, prin inserri repetate n faa
listei;
S se aeze lista creat;
Se citete un numr. S se determine dac acesta se a printre elementele listei create;
S se insereze un numr ntr-o poziie n list, numrul i poziia ind introduse (citite) prin
intermediul intrrii standard;
S se stearg un element din list, poziia de tergere ind dat la intrarea standard;

= (x ; x ; :::; x ) i Y = (y ; y ; :::; y ) dou liste liniare dublu nlnuite. Scriei un program


1

C/C++ care:




s uneasc cele dou liste n una singur:

= (x ; x ; ::; x
1

s interclasese cele doua liste astfel:

 Z
 Z

= (x ; y ; x ; y ; :::; x
= (x ; y ; x ; y ; :::; x
1

; y1 ; y2 ; :::; ym

; ym ; xm+1 ; :::; xn dac m < n,


dac n <
m.
n ; yn ; yn+1 ; :::; ym

);

Capitolul

Liste circulare

7.1

Aspecte generale

Deniie. O list circular este o list simpl n care

(ultimul; capul) 2 R

Rezult urmtoarele:




capul listei are predecesor direct ultimul element ;


ultimul element are un succesor direct capul listei;

L secvenializarea coleciei C conform cu relaia de ordine dat de nchiderea


R n f(ultimul; capul)g atunci L = (e ; e ; : : : ; e ); capul = e ; ultimul = e i R =
f(e ; e ); (e ; e ) : : : (e ; e )(e ; e )g
Dac se noteaz cu

tranzitiv a lui
1

O list circular poate  ordonat dar aceasta presupune denirea pe mulimea poziiilor a unei relaii
de tipul lui

R. Acest gen de organizare a spaiului poziiilor va  detaliat n seciunea referitoare la cozi

circulare. In consecin listele circulare vor  analizate n cele ce urmeaz doar ca structuri nlnuite.

7.2

Liste circulare simplu nlnuite

Un element al unei liste circulare simplu nlnuite are aceai structur ca i elementele unei liste liniare
simplu nlnuite.

7.2.1 Operaii cu liste circulare simplu nlnuite


Parcurgerea
Operaia de parcurgere a unei liste circulare simplu nlnuite se denete ca ind operaia de explorare
sistematic bazat pe accesul n colecia referit de list prin capul al acesteia i accesul secvenial la
celelalte elemente,conform cu informaia de nlanuire
Fie

succ, n

scopul prelucrrii elementelor listei.

variabila care conine adresa elementului curent accesibil.

IF c6=o THEN // lista nu este vid


prelucrare (data(c));
p c;
WHILE succ(p)6=c DO
prelucrare (data(succ(p))) //ex: afiarea elementului
p succ(p) //trece la urmtorul
END_WHILE
END_IF
37

Mitic Craus - Structuri de date i algoritmi


Observaie.

38

Consultarea, modicarea unui element al listei i identicarea elementului minim/maxim

sunt opertii care presupun parcurgerea parial sau total a listei.


Un prototip de parcugere parial poate  urmtoarea secven de pseudocod:

IF not condiie(c) and c6=o THEN // lista nu este vid


prelucrare (data(c));
p c;
WHILE not condiie(succ(p)) and succ(p)6=c DO
prelucrare (data(succ(p))) //ex: afiarea elementului
p succ(p) //trece la urmtorul
END_WHILE
END_IF
Inserarea

Situiile tipice de inserare a unui element ntr-o list circular simplu nlnuit sunt aceleai ca la
liste liniare simplu nlnuite:

 inserarea n fa listei (naintea capului listei);


 inserarea n interiorul listei;
 inserarea dup ultimul element al listei.

a) Inserarea n fa listei (naintea primului element al listei)


-
>

-q
>

>

q q q

-~ i

1 

parcurgere lista
q conine adresa ultim element

2 

succ(q)

3 

succ(p)

4 

b) Inserarea n interiorul listei


Variabila

va adresa elementul dup care se face inserarea.


-

-

-~

rrr

1 

succ(p)

succ(q)

2 

succ(q)

Mitic Craus - Structuri de date i algoritmi


Observaie.

39

Inserarea n interiorul unei liste circulare simplu nlnuite nu difer cu nimic de inserarea

n interiorul unei liste liniare simplu nlnuite.

c) Inserarea dup ultimul element al listei


Variabila

adreseaz ultimul element al listei.


-

-

-~

rrr

1 

succ(p)

succ(q)

2 

succ(q)

Observaie.

Dei inserarea dup ultimul element al listei ar putea  asimilat cu inserarea naintea

capului listei prima difer de a doua prin aceea ca adresa ultimului element este cunoscut iar capul listei
nu se schimb.

tergerea
tergerea unui element dintr-o list circular simplu nlnuit comport urmtoarele situaii:

 elementul ce se dorete a  ters este capul listei;


 elementul ce se dorete a  ters este situat n interiorul listei;
 elementul ce se dorete a  ters ultimul element al listei.
a) tergerea primului element al listei
q
p
3

-- T

- -
TT >
I
5

1 : Parcurgere list; // pointerul


2 :
3 :
4 :
5 :

succ(q)
succ(c);
p
c;
c
succ(c);
free_sp(p);

1
qqq q

--

va conine adresa elementului ce pointeaz spre

b) tergerea unui element situat n interiorul listei


Variabila

va adresa elementul din faa celui care va  ters.

Mitic Craus - Structuri de date i algoritmi

40


q

Observaie.

-- SS S *
1

q q q

2 

succ(p)

3 

free_sp(q)

1 

succ(p)
succ(q)

Nici tergerea n interiorul unei liste circulare simplu nlnuite nu difer de tergerea n

interiorul unei liste liniare simplu nlnuite.

c) tergerea ultimului element al listei


Variabila

va adresa elementul ce precede ultimul element al listei.


p

-- AA
A
3

1
q

OBSERVAIE.

1 
2 
3 

q
succ(p)
succ(p)
c
free_sp(q)

O list circular simplu nlnuit poate  specicat ntr-un mai protabil prin

ultimul element (predecesorul capului listei). Acest mod de identicare a unei astfel de liste ar elimina
necesitatea parcurgerii listei atunci cnd urmeaz o inserie n faa listei sau tergerea capului listei.

7.2.2 Moduri de denire a adresei elementului care urmeaz a  procesat


ntr-o list circular simplu nlnuit
Operaia de inserare ntr-o list circular simplu nlnuit
Exist posibiliti diferite de a specica poziia n care se dorete inserrea unui element n list:

situaia n care poziia de inserat este dat prin numrul de ordine al elementului ce trebuie s e
inserat n list;

situaia n care poziia de inserat este dat prin valoarea elementului dup care sau nainte de care
se face inserarea;

situaia n care poziia de inserat poate  dat implicit prin valoarea elementului de inserat - cazul
listelor sortate.

n consecin inserarea unui element ntr-o list are algoritmi diferii, funcie de datele de nserare de
care se dispune.

Inserarea n faa unui element specicat prin informaia de coninut a elementului


Funcia

insert nscrie un

INSERT(c,a,b)

element n faa altui element dintr-o list

//c - lista (pointer la primul element)

c:

Mitic Craus - Structuri de date i algoritmi

41

//a - informaia de coninut a elementului de inserat


//b - informaia de coninut a elementului n faa cruia se insereaz
p get_sp();
data(p) a;
IF c=o THEN // lista este vid
// inserare element adresat de p (contine informaia a)
c p;
succ(c) c;
ELSE
q c
IF data(c)=b THEN // inserare n faa primului elemet al listei
WHILE succ(q)6=c DO // parcurge lista pna la ultimul element
q succ(q)
END_WHILE // q adreseaza ultimul element
// inserare element ce conine a n faa primului elemet al listei
succ(q) p;
succ(p) c;
c p;
ELSE // inserare in interiorul listei sau dup ultimul element
// caut n list elementul ce conine b
WHILE succ(q)6=c and data(succ(q))6=b DO
q succ(q);
END_WHILE
IF data(succ(q))6=b THEN
eroare ("Elementul ce ar trebui s conin b nu se afl
n list")
ELSE // elementul ce conine b este curent accesibil
// inserare element ce conine a n faa element ce conine b
succ(p) succ(q);
succ(q) p;
END_IF
END_IF
END_IF

END

Operaia de tergere dintr-o list circular simplu nlnuit


i n acest caz exist posibiliti diferite de a specica poziia n care se dorete tergerea unui element
din list:

situaia n care poziia de ters este dat prin numrul de ordine al elementului ce trebuie s e
ters din list;

situaia n care poziia de ters este dat prin informaia de coninut a elementului de ters sau prin
informaia de coninut a elementului dup care sau nainte de care se face tergerea.

n consecin i tergerea unui element ntr-o list circular simplu nlnuit are algoritmi diferii,
funcie de datele de tergere de care se dispune.

tergerea elementului din faa unui element specicat prin valoarea elementului
Pseudocodul pentru o astfel de funcie de tergere poate  de forma:

DELETE(c,a)

//c - pointer la primul element

Mitic Craus - Structuri de date i algoritmi

42

//a - informaia de coninut a elementului care trebuie ters


IF c=o THEN
eroare ("Lista este vid")
ELSE
p c;
// caut n list elementul ce conine a
WHILE succ(p)6=c and data(succ(p))6=a DO
p succ(p)
END_WHILE
IF data(succ(p))6=a THEN // succ(p)=c
eroare ("Elementul ce ar trebui s conin a nu se afl
n list")
ELSE // data(succ(p))=a  elementul de sters este curent accesibil
IF succ(p)=c THEN // capul listei conine informaia a
q p
WHILE succ(q)6=c DO // parcurge lista pn la ultimul element
q succ(q)
END_WHILE // q adreseaza ultimul element
// terge capul cozii
succ(q) succ(c);
free_sp(c);
c succ(q);
ELSE // elementul adresat de succ(p) conine informaia a
// terge elementul a crui adresa este dat de succ(p)
q succ(p);
succ(p) succ(q);
free_sp(q)
END_IF END_IF
END_IF

END

7.2.3 Exerciii
1. Se citete, prin intermediul intrrii standard, un ir de numere ntregi.







S se plaseze numerele citite ntr-o list circular simplu nlnuit, prin inserri repetate n
faa listei;
S se aeze lista creat;
Se citete un numr. S se determine dac acesta se a printre elementele listei create;
S se insereze un numr ntr-o poziie n list, numrul i poziia ind citite introduse prin
intermediul intrrii standard;
S se stearg un element din list, poziia
de tergere ind dat la intrarea standard;

2. S se scrie un algoritm care inverseaz legturile ntr-o list circular simplu nlnuit.
3. Fie

= (x ; x ; :::; x ) i Y = (y ; y ; :::; y ) dou liste circulare simplu nlnuite.


1

program C/C++ care:




s uneasc cele dou liste n una singur:

= (x ; x ; ::; x

s interclasese cele doua liste astfel:

 Z

= (x ; y ; x ; y ; :::; x
1

; ym ; xm+1 ; :::; xn

; y1 ; y2 ; :::; ym

) dac m <= n,

);

Scriei un

Mitic Craus - Structuri de date i algoritmi


 Z

= (x ; y ; x ; y ; :::; x
1

; yn ; yn+1 ; :::; ym

4. (Problema lui Joseph) Se consider

43

) dac n <= m.

n persoane aranjate n cerc.

p0
m-a persoan; cer-

ncepnd cu o poziie particular

se efectueaz numrarea persoanelor i, n mod brutal se execut ecare cea de-a

cul se inchide dup eliminarea unei persoane. Execuia se termin cnd rmne o singur persoan;
aceasta va rmne n via.




S scrie o funcie C/C++ care s aeze persoanele n ordinea n care au fost executate;
Presupunnd c se dorete salvarea unei anume persoane, s se scrie o funcie C/C++ care s
determine pozitia

p0

astfel nct, dac numratoarea ncepe cu

i0 ,

atunci persoana salvat s

e cea dorit.

7.3

Liste circulare dublu nlnuite

Elementele unei liste circulare dublu nlnuite au aceai structur ca i elementele unei liste liniare dublu
nlnuite.

7.3.1 Operaii cu liste circulare dublu nlnuite


Parcurgerea
Fie

variabila care adreseaz elementul curent accesibil.

Parcurgere nainte

IF c6=o THEN // lista nu este vid


prelucrare (data(c));
p c;
WHILE succ(p) 6= c DO
prelucrare (data(succ(p))) //ex: afiarea elementului
p succ(p) //trece la urmtorul
END_WHILE
END_IF
Parcurgere napoi

IF c6=o THEN // lista nu este vid


prelucrare (data(c));
p c;
WHILE pred(p) 6= c DO
prelucrare (data(pred(p))) //ex: afiarea elementului
p pred(p) //trece la predecesor
END_WHILE
END_IF
O parcugere parial nainte poate  urmtoarea secven de pseudocod:

IF not condiie(c) and c6=o THEN // lista nu este vid


prelucrare (data(c));
p c;
WHILE not condiie(succ(p) and succ(p)6=c DO
prelucrare (data(succ(p))) //ex: afiarea elementului
p succ(p) //trece la succesor
END_WHILE
END_IF
Parcugerea parial napoi poate  exprimat astfel:

Mitic Craus - Structuri de date i algoritmi

44

IF not condiie(c) and c6=o THEN // lista nu este vid


prelucrare (data(c));
p c;
WHILE not condiie(pred(p) and pred(p)6=c DO
prelucrare (data(pred(p))) //ex: afiarea elementului
p pred(p) //trece la predecesor
END_WHILE
END_IF
Inserarea
Exist trei situaii tipice de inserare a unui element ntr-o list circular dublu nlnuit:

 inserarea n faa primului element al listei;


 inserarea n interiorul listei.
 inserarea dup ultimul element al listei.
Se presupune c elementul care urmeaz a  inserat are adresa coninut ntr-o variabil

p.

a) Inserarea n faa primului element al listei

O
p


i

1
4

-q

1 :
2 :
3 :
4 :
5 :

6
r

 -

q
q

 %

q q q

q
 -

pred(p) pred(c)
succ(p) c
succ(pred(c)) p
pred(c) p
c
p

b) Inserarea n interiorul listei


Se presupune ca elementul nainte sau dup care urmeaz a se face inserarea are adresa cunoscua
(coninut ntr-o variabil

q).

Inserarea naintea elementului adresat de q

Mitic Craus - Structuri de date i algoritmi

z
 3


4
1

2
q

JJ -q
q

1 :
2 :
3 :
4 :

45

q
q

 -

 -

 -

succ(p) q
succ(pred(q)) p
pred(p) pred(q)
pred(q) p

Inserarea dup elementul adresat de q

1 :
3 :
4 :

z
 1

2 :


2
3

4
q

JJ -q

pred(p) q
pred(succ(q)) p
succ(p) succ(q)
succ(q) p

c) Inserarea dup ultimul element al listei

q
q

 -

Mitic Craus - Structuri de date i algoritmi

46

Se presupune c ultimul element al listei dup care urmeaz a se face inserarea are adresa cunoscut
(coninut ntr-o variabil

q).

-  q

OM
2

?
 --


 
4

 -

q q q

3
1 :
2 :
3 :
4 :

pred(p)
succ(q))
pred(c)
succ(p)

q;
p;
p;
c;

tergerea
tergerea unui element dintr-o list circular dublu nlnuit comporta urmtoarele situaii:

 elementul ce se dorete a  ters este capul listei;


 elementul ce se dorete a  ters este situat n interiorul listei
 elementul ce se dorete a  ters este ultimul element al listei.

Observaie.

n ultimul caz se presupune c elementul dup sau naintea cruaia urmeaz a se face

tergerea are adresa cunoscut (coninut ntr-o variabil

p).

a) tergerea capului listei

!!
!
  >
"
"
"
2

9
--* A 
 AA H -
3

q
q

pq pq pq

1 :
2 :

p c
succ(pred(c)) succ(c)

Mitic Craus - Structuri de date i algoritmi


3 :
4 :
5 :

47

pred(succ(c)) pred(c)
c succ(c)
free_sp(p)

b) tergerea unui element situat n interiorul listei


Variabila

adreseaz elementul din faa celui care va  ters.

 -

1 :
2 :
3 :
4 :

c
p

j
 - @@  -~
@
}

 - *

j
 -

 - @@  -~
@
}
4

q
q

3 :

adreseaz elementul care va  ters.

2 :

 - *

q succ(p);
succ(p) succ(q);
pred(succ(q)) p;
free_sp(q);

Variabila

1 :

q
q

q pred(p);
succ(q) succ(p);
pred(succ(p)) q;

Mitic Craus - Structuri de date i algoritmi


4 :

free_sp(p);

Variabila

adreseaz elementul situat dup cel care va  ters.

 -

j
 - @@  -~
@
}
4

q
q

1 :
2 :
3 :
4 :

48

q
q

 - 

q pred(p);
pred(p) pred(q);
succ(pred(q)) p;
free_sp(q);

a) tergerea ultimului element al listei


Variabila

adreseaz penultimul element al listei.

-  q

q
q

 
 :

pq qp pq

c
1 :
2 :
3 :

free_sp(succ(p));
succ(p) c;
pred(c) p;

Variabila

adreseaz ultimul element al listei.

q
q

 -- AA
A
q

Mitic Craus - Structuri de date i algoritmi

49

-  q

q
q

!!!
2

 :
pq pq pq

1 :
2 :
3 :

q
q

 - AA
A

succ(pred(p)) c;
pred(c) pred(p);
free_sp(p);

7.3.2 Moduri de denire a adresei elementului care urmeaz a  procesat


ntr-o list circular dublu nlnuit
Operaia de inserare ntr-o list circular dublu nlnuit
i n cazul listelor circulare dublu nlnuite exist posibiliti diferite de a specica poziia n care
se dorete inserarea unui element n list. Acestea sunt aceleai ca la listele circulare simplu nlnuite.
Algoritmii difer ns de cei din cazul listelor circulare simplu nlnuite. Aceasta se datoreaz faptului c
operaia de inserare trebuie s actualizeze dou informaii de nlnuire (pred i

succ) i nu

una (succ).

De exemplu pentru inserarea n faa unui element specicat prin informaia de coninut, un prototip
de pseudocod este urmtorul:

INSERT(c,a,b)

// c - pointer la primul element


// a - informaia de coninut a elementului de inserat
// b - informaia de coninut a elementului n faa cruia
//
se insereaz
p get_sp();
data(p) a;
IF c=o THEN
eroare("Lista este vid");
ELSE
IF data(c)=b THEN // inserare in faa primului element al listei
pred(p) pred(c);
succ(p) c;
c p;
ELSE // inserare n interior sau dup ultimul element
// caut n list elementul ce conine a
q c;
WHILE succ(q)6=c and data(succ(q))6=b DO
p succ(q);
END_WHILE
IF data(succ(q))6=b THEN
eroare("Elementul ce ar trebui s conin b nu se afl
n list");
ELSE // elementul ce conine b este curent accesibil
// inserare element ce conine a
pred(p) q;

Mitic Craus - Structuri de date i algoritmi

50

pred(succ(q)) p;
succ(p) succ(q);
succ(q) p;
END_IF
END_IF
END_IF

END

Operaia de tergere dintr-o list circular dublu nlnuit


in n acest caz exist posibiliti diferite de a specica poziia n care se dorete tergerea unui
element din list:
Pentru tergerea elementului din faa unui element specicat prin informaia de coninut a elementului,
pseudocodul pentru o astfel de oepraie poate  de forma:

DELETE(c,a)

// c - pointer la primul element


// a - informaia de coninut a elementului care trebuie ters
IF c=0 THEN
eroare ("Elementul nu se afl n list");
ELSE
IF data(c)=a THEN// tergerea primului element al listei
p c;
c succ(c);
pred(c) pred(p);
free_sp(p);
ELSE
p c;
// caut n list elementul ce conine a
WHILE succ(p)6=c and data(succ(p))6=a DO
p succ(p);
END_WHILE
IF succ(p)6=a THEN
eroare ("Elementul ce ar trebui s conin a nu se afl
n list");
ELSE // tergere n interiorul listei sau a ultimului element
q succ(p);
succ(p) succ(q);
pred(succ(q)) p;
free_sp(q);
END_IF
END_IF
END_IF

END

7.3.3 Exerciii
1. Se citete, prin intermediul intrrii standard, un ir de numere intregi.





S se plaseze numerele citite ntr-o list circular dublu nlnuit, prin inserri repetate n
faa listei;
S se aeze lista creat;
Se citete un numr. S se determine dac acesta se a printre elementele listei create;

Mitic Craus - Structuri de date i algoritmi



2. Fie

51

S se insereze un numr ntr-o poziie n list, numrul i poziia ind citite (introduse) prin
intermediul intrrii standard;
S se stearg un element din list, pozii de tergere ind dat la intrarea standard;

= (x ; x ; :::; x ) i Y = (y ; y ; :::; y ) dou liste circulare dublu nlnuite. Scriei un modul


1

C/C++ care:




s uneasc cele dou liste n una singur:

s interclasese cele doua liste astfel:

 Z
 Z

= (x ; y ; x ; y ; :::; x
= (x ; y ; x ; y ; :::; x
1

= (x ; x ; ::; x
1

n ; yn ; yn+1 ; :::; ym

; y1 ; y2 ; :::; ym

) dac m <= n,
) dac n <= m.

; ym ; xm+1 ; :::; xn

);

Capitolul

Stive i Cozi

8.1

Stive

Deniie.

O stiv este o structur de date de tip container (depoziteaz obiecte de un anumit tip),

organizat dup principiul LIFO (Last In First Out).


Stiva se poate asemna cu un recipient n care se pun i se pot scoate diferite obiecte. Operaia care

push, iar cea


vrful stivei.

pune obiectele n stiv se numete


accesibil pentru stiv se numete

care scoate obiecte din stiv se numette

pop.

Captul

Aadar:

push : insereaz un element n vrful stivei;


pop : citee i terge elementul din vrful stivei;
top : consult (citete) elementul din vrful stivei.
pop

push

O stiv poate  implementat ca o list liniar pentru care operaiile de acces (inserare, tergere,
accesare element) sunt restricionate astfel:




inserarea se efectueaz n faa primului element al listei (capul)


tergerea acioneaz doar asupra primului element al listei

Dac STACK este o structur de tip stiv i ATOM este tipul obiectelor coninute n stiv, atunci
operaiile care denesc o structur de tip stiv sunt urmtoarele:

CREATE()

! STACK

Operaia CREATE nu primete parametri, creeaz o stiv care pentru nceput este vid (nu conine
nici un obiect).

PUSH (STACK, ATOM)

! STACK

Operaia PUSH primete ca parametri o stiv i un obiect i produce stiva modicat prin adugarea
obiectului n stiv.

52

Mitic Craus - Structuri de date i algoritmi

POP (STACK)

53

! STACK, ATOM

Operaia POP primete ca parametri o stiv pe care o modic scond un obiect. De asemenea,
produce ca rezultat obiectul scos din stiv.

TOP (STACK)

! ATOM

Operaia TOP ntoarce ca rezultat obiectul din vrful stivei pe care o primete ca parametru.

! boolean

ISEMPTY (STACK)

Operaia ISEMPTY este folosit pentru a testa dac stiva este vid.

8.2

Cozi

Deniie. O coad este o structur dinamic care inserarea se face la un capt (la sfrit), iar tergerea
se face la cellalt capt al cozii (la nceput). Partea din fa a cozii (primul element) se numete
iar partea din spate (ultimul element) se numete

end.

front,

Deci:

add (put) : insereaz n coad un element;


del (get) : terge din coad un element;
front : citete elementul din capul cozii;
add

- del

O coad poate  implementat ca o list liniar n care operaiile de acces sunt restricionate astfel:




inserarea n fat listei


tergerea de la sfritul listei.

Dac QUEUE este o structur de tip coad i ATOM este tipul obiectelor coninute n coad, atunci
operaiile caracteristice unei structuri de tip coad sunt urmtoarele:

PUT(QUEUE, ATOM)

! QUEUE

Adaug un element la coad.

GET(QUEUE)

! QUEUE, ATOM

Elimin primul element din coad. Returneaz elementul eliminat.

FRONT(QUEUE)

! ATOM

Returneaz primul element din coad, fr a-l elimina din coad.

ISEMPTY(QUEUE)

! boolean

Testeaz dac coada este vid.

8.3

Implementri de stive

8.3.1 Stive ordonate


O stiv poate  organizat pe un spaiu de memorare de tip tablou (vector). Astfel, o stiv va  format
dintr-un vector de elemente de tip ATOM si un indicator (index) al virfului stivei.

Notaii:

S : stiva;
S:vect : vectorul n care se reprezint
S:top : indicele vrfului stivei.

elementele stivei

S;

Mitic Craus - Structuri de date i algoritmi

54

Elementele sunt memorate, aadar, unul dup altul n vectori, neind neaprat n ordine cresctoare.
Zona de memorat trebuie s conin aceste dou informaii:
Condiia de stiv vid este:

S.top =

S.top i S.vect.

0.

n C++ declaraia de structur pentru tipul STACK va  urmtoarea:

struct Stack{
int top; // "top of stack"
atom vect[DIMSTACK];
};
Operaiile care denesc structura de stiv ordonat n C++ vor  implementate prin urmtoarele
funcii:

void initStack(Stack& S);


void push(Stack& S, Atom a);
Atom pop(Stack& S);
Atom top(Stack& S);
int isEmpty(Stack& S);
Operaiile specice stivelor ordonate pot  descrise n pseudocod astfel:

PUSH(S,a)

IF S.top >= DIMMAX THEN


eroare (Stiva plin);
ELSE
S.top S.top+1;
S.vect[S.top] a; //atomul este pus pe prima poziie
END_IF

END

POP(S)

IF S.top = 0 THEN
eroare (Stiv vid);
ELSE
S.top S.top-1;
END_IF

END
Observaie.

Se obinuiete ca, pe lng tergerea elementului, funcia

din list.

TOP(S)

IF S.top = 0 THEN
eroare (Stiv vid);
ELSE
return(S.vect[S.top]);
END_IF

END

ISEMPTY(S)

return(S.top=0);

END

pop s returneze elementul scos

Mitic Craus - Structuri de date i algoritmi

55

8.3.2 Stive nlnuite


O stiv poate  implementat ca o list liniar simplu nlnuit pentru care operaiile de acces se fac

push va nsemna inserare n prima poziie


pop va nsemna tergerea primului element din list.
<STACK> va  echivalat n cazul stivelor nlnuite cu tipul <pointer la capul listei>.

numai asupra primului element din list. Deci, operaia

din

list (n fa), iar


Tipul

pointerul la primul element din nlnuire. Condiia de stiv vid va 

= 0.

Fie

Dac informaiile de nlnuire sunt materializate ca pointeri atunci n C++ un declaraiile vor 
urmtoarele:

struct Element{
Atom data;
Element* succ;
};
typedef Element* Stack;
void initStack(Stack& S);
void push(Stack& S, Atom val);
Atom pop(Stack& S);
Atom top(Stack S);
int isEmpty(Stack S);
Funciile care implementeaz operaiile de acces vor avea prototipuri similare cu cele date pentru
stivele ordonate:

PUSH(S,a)

p get_sp();
data(p) a;
succ(p) S;
S p;

END

POP(S)

IF S=0 THEN
eroare (Stiv vid);
ELSE
p S;
S succ(S);
free_sp(p);
END_IF

END

TOP(S)

IF S=0 THEN
eroare (Stiv vis);
ELSE
return(data(S));
END_IF

END

ISEMPTY(S)

return(S=0);

END

Mitic Craus - Structuri de date i algoritmi


8.4

56

Exerciii

1. Forma polonez (notaia posxat) a unei expresii aritmetice se caracterizezaz prin aceea c operatorii apar n ordinea n care se execut operaiile la evaluarea expresiei. De aceea evaluarea unei
expresii n forma polonez se face parcurgnd ntr-un singur sens expresia i executnd operaiile
innd seama de paritatea lor.
Denirea recursiv a expresiilor n forma polonez (f.p.) este urmtoarea:
1) Pentru orice operand (constant sau variabil)
2) Dac

este o expresie de forma

respectiv f.p. ale expresiilor


3) Daca

E opE

1 i E 2

2 , f.p.

E, E

este forma polonez a operandului

0 0
0
a expresiei este E 1 E 2 op unde E 1

este o expresie de forma (E ) f.p. a expresiei

20 sunt

1 este de asemenea f.p. a expresiei E

Exemple: (9-5)+2 are f.p. 95-2+ 9-(5+2) are f.p. 952+-

Obs.

Expresiile n forma polonez nu conin paranteze.

Un algoritm simplu de evaluare a expresiilor n forma polonez este urmtorul:

// Expresia se afl ntr-un tablou s cu elemente simboluri de


// tip operand sau operator binar
i

0;

WHILE (nu s-a terminat irul s) DO


IF (s[i] este operand THEN
depune s[i] n stiv
ELSE
IF(s[i] este operator) THEN
extrage din stiva dou simboluri t1 si t2;
execut operaia s[i] asupra lui t1 si t2;
depune rezultatul in stiv
ELSE
semnalizeaz eroare
END_IF
END_IF
i i+1
END_WHILE
Obs. Algoritmul presupune c expresiile conin doar operatori binari.
Scrieti un program C (C++) care s rezolve problema evalurii unei expresii date n forma polonez.
2. O alt form fr paranteze a unei expresii aritmetice este forma prexat.
Exemplu: (9-5)+2 are forma prexat +-952
a. Dai o deniie recursiv pentru forma prexat a unei expresii aritmetice.
b. Scriei un program C (C++) de trecere a unei expresii din forma postxat n forma prexat.
c.

Scrieti un program C (C++) care s rezolve problema evalurii unei expresii date n forma

prexat.

Mitic Craus - Structuri de date i algoritmi


8.5

57

Implementri de cozi

8.5.1 Cozi ordonate liniare


O coad poate  organizat pe un spaiu de memorare de tip tablou (vector).
Sunt necesari doi indicatori:

head :
tail :

indic primul element care urmeaz s e scos.


indic locul unde va  pus urmtorul element adugat la coad.

Condiia coad vid este echivalent cu:

head = tail.

Iniial, indicatorii vor  iniializai astfel

nct s adreseze ambii primul element din vector.


Operaia

put

nseamn:

 V[tail] primete Atomul adugat;


 incrementeaz tail.
Operaia

get

nseamn:

 ntoarce V[head];
 incrementeaz head.
Se observ c adugri i tergeri repetate n coad deplaseaz coninutul cozii la dreapta, fa de
nceputul vectorului. Pentru a evita acest lucru ar trebui ca operaia

get s deplaseze la stnga coninutul

cozii cu o poziie. Primul element care urmeaz a  eliminat din coad va  ntotdeauna pe prima poziie,
indicatorul

head

pierzndu-i utilitatea.

Dezavantajul acestei soluii const n faptul c operaia

necesit o parcurgere a cozii.

Notaii:
Q : coada;
Q.vect : vectorul n care sunt memorate elementele cozii;
Q.head : indicele elementului ce va  scos din coad la urmtoarea operaie get;
Q.tail : indicele (poziia) n care va  memorat urmtorul element adugat la coad.
Condiia coad vid este Q.head=Q.tail.
Declaraiile in C++ pentru o astfel de coad vor  urmtoarele:

struct Queue{
int head,tail;
Atom vect[DIMMAX]; };
void initQueue(Queue& Q);
void put(Queue& Q, Atom a);
Atom get(Queue& Q);
Atom front(Queue& Q);
int isEmpty(Queue& Q);
Operaiile specice cozilor ordonate liniare pot  descrise n pseudocod astfel:

PUT(Q,a)

IF Q.tail > DimMax THEN


eroare (Coad plin);
ELSE
Q.vect[Q.tail] a;
Q.tail Q.tail+1;
END_IF

END

GET(Q)

IF Q.head=Q.tail THEN
eroare (Coad vid);
ELSE
Q.head Q.head+1;

get

Mitic Craus - Structuri de date i algoritmi

58

return Q.vect[Q.head-1];
END_IF

END
FRONT(Q)

IF Q.head=0 THEN
eroare(Coad vid);
ELSE
return data(Q.head);
END_IF

END
ISEMPTY(Q)

return (Q.head=c.tail);

END

8.5.2 Cozi ordonate circulare


Pentru a obine o coad circular vom porni de la o coad liniar simpl (cu doi indicatori) i vom face
n aa fel nct la incrementarea indicatorilor

head

tail,

cnd acetia ating ultima poziie din vector

s se continue cu prima poziie din vector.


Funcia urmtoare poate realiza aceast cerin:

NextPoz(int index)

IF(index<DimVector-1) return index+1


ELSE return 0

END
unde

DimVector este

dimensiunea vectorului n care se memoreaz elementele cozii.

Coninutul cozii va arta aa:


1

head

tail

sau aa:
5

head

head=tail.

Condiia coad vid rmne echivalent cu:

head

sau, dac:

tail

tail=DimVector.
q

tail

tail+1=head
q

head

tail

Coada va  plin dac:

head=1

Mitic Craus - Structuri de date i algoritmi

59

Ambele situaii sunt coninute n condiia:

NextPoz(tail)=head

//condiia coad plin.

get la urmtoarele inserri n coad.


DimMax elemente.

Coada circular ordonat asigur reutilizarea spaiului eliberat de


n coada circular de dimensiune

DimMax pot

 memorate

Coada plin se realizeaz n dou situaii:

Q.head=1 i Q.tail=DImMax;
Q.tail+1=Q.head.
Condiia Q.head=inc(Q.tail) reunete
a)

b)

situaiile a) i b).

n cazul cozilor circulare se modic doar operaiile

PUT

GET:

PUT(Q,a)

IF Q.head=inc(Q.tail) THEN
eroare(Coad plin);
ELSE
Q.vect[Q.tail] a;
Q.tail inc(Q.tail);
END_IF

END

GET(Q)

IF Q.head=Q.tail THEN
eroare(Coad vid);
ELSE
a Q.vect[Q.head];
Q.head inc(Q.head);
return(a)
END_IF

END

8.5.3 Cozi nlnuite liniare


O coad poate  implementat printr-o list liniar simplu nlnuit la care operaiile de acces sunt

restricionate corespunztor.
a

head

tail

nil

Este nevoie de doi




indicatori

(pointeri):

head :

indic primul element din coad (primul care va  scos);

tail :

indic ultimul element din coad (ultimul introdus).

O coad vid va avea:

head=tail=nil.

n mod obinuit, adugarea unui element n coad modic numai


numai

head.

ntr-un mod special trebuie s e tratate cazurile:

 adugare ntr-o coad vid

iniial: head=tail=nil;
nal: coad cu un element.

tail,

iar tergerea unui element

Mitic Craus - Structuri de date i algoritmi


head

nil

tail
q

 tergere dintr-o coad cu un element


iniial: coad cu un element;
nal: head=tail=nil.

n aceste cazuri se modic att

Notaii:
Q.head : pointer
Q.tail : pointer
Q : coada.

head, ct

tail.

la primul element din coad;


la ultimul element din coad;

Condiia de coad vid este

head=0.

n C++ pot  utilzate urmtoarele declaraii:

struct Element{
Atom data;
Element* succ;
};
struct Queue{
Element* head,tail;
};
struct Queue{
int head,tail;
Atom vect[DIMMAX]; };
void initQueue(Queue& Q);
void put(Queue& Q, Atom a);
Atom get(Queue& Q);
Atom front(Queue Q);
int isEmpty(Queue Q);
Operaiile cozii nlnuite vor  urmtoarele:

PUT(Q,a)

p get_sp();
data(p) a;
succ(p) 0;
IF Q.head=0 THEN
Q.head p;
Q.tail p;
ELSE
succ(Q.tail) p;
Q.tail p;
END_IF

END

GET(Q,a)

IF Q.head=0 THEN
eroare(Coad vid);
ELSE
p Q.head;
Q.head succ(Q.head);

60

Mitic Craus - Structuri de date i algoritmi

61

free_sp(p);
return(a);
END_IF

END

FRONT(Q)

IF Q.head=0 THEN
eroare(Coad vid);
ELSE
return data(Q.head);
END_IF

END

ISEMPTY(Q)

return(Q.head=0);

END

Exist aici un element de redundan: ar  convenabil s nu mai avem spaiu suplimentar de memorare, ci s avem un singur pointer ca s putem manevra coada. De aceea, apar utile cozile nlnuite
circulare.

8.5.4 Cozi nlnuite circulare


Dac reprezentm coada printr-o structur circular, va  nevoie de un singur pointer prin intermediul
cruia se pot face ambele operaii de adugare i tergere din coad:

primul
q

...

tail

ultimul
q

Fie:

: pointer la ultimul element din coad;

succ(Q) :

Operaiile de plasare i de scoatere din coad sunt:

PUT(Q,a)

p get_sp();
data(p) a;
IF Q=0 THEN
Q p;
succ(Q) p;
ELSE
succ(p) succ(Q);
succ(Q) p;
Q p;
END_IF

END

GET(Q)

IF Q=0 THEN eroare(Coad vid);


ELSE
IF Q=succ(Q); THEN
a data(Q);
free_sp(Q);
Q 0;

pointer la primul element din coad.

Mitic Craus - Structuri de date i algoritmi

62

return(a);
ELSE
p succ(Q);
succ(Q) succ(p);
a data(p);
free_sp(p);
return(a);
END_IF
END_IF

END

FRONT(Q)

IF Q=0 THEN
eroare(Coad vid);
ELSE
return data(succ(Q));
END_IF

END

ISEMPTY(Q)

return(Q=0);

END
8.6

Exerciiu

Denim domeniu ca ind o zon din ecranul grac care conine pixeli nvecinai direct sau indirect, pe
vertical sau orizontal i care au aceeai culoare.
S se scrie un program C/C++ care schimb culoarea unui domeniu, pornind de la un pixel oarecare
din acel domeniu.

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