Sunteți pe pagina 1din 24

Acest document este similar seciunii 2.

7 din "Introducere n Analiza Algoritmilor",


coninutul fiind extins cu:
1.
2.
3.
4.

Specificarea formal a tipului T Ring


Verificarea corectitudinii specificaiei T Ring
Verificarea implementrii tipului T Ring ca o pereche de liste T List
Rescrierea Haskell a specificaiei T Ring i implementarea
T Ring = AbspT List, T List

5. Dezvoltarea unui algoritm corect pentru sortarea unei liste de chei folosind un inel.

2.7 Analiz amortizat


Tehnica de analiz a complexitii, aa cum a fost discutat n seciunile
precedente, nu ine seama de posibila comportare neuniform a algoritmului studiat.
Analiza este realizat punctual, pentru un singur pachet de date, i, de regul, pentru
cazul cel mai defavorabil. Este ns posibil ca un algoritm s fie ineficient n cazurile
defavorabile, dar performant n celelalte cazuri. Dac situaiile defavorabile apar relativ
rar, atunci pe ansamblu, pentru o mulime de pachete de date, algoritmul poate avea o
comportare acceptabil, iar costul secvenei de operaii efectuate de algoritm poate
rezulta sczut. Astfel, devine interesant studiul costurilor secvenelor posibile de
operaii ce pot fi efectuate de algoritm, cu condiia ca secvenele s acopere cazurile
defavorabile. Analiza complexitii amortizate (sau pe scurt analiza amortizat) a unui
algoritm are exact acest scop: determinarea marginii superioare a costului unei
secvene oarecare de operaii i, totodat, calculul costului mediu al operaiilor
algoritmului.

Introducere n analiza algoritmilor

Costul mediu costa(op) al unei operaii op, calculat pentru o secven oarecare
S de operaii ce acoper cazurile cele mai defavorabile, se numete cost amortizat al
operaiei, iar suma costa(op) este o margine superioar a costului secvenei S.
opS

2.7.1 Inel unidirecional


Ca baz pentru discutarea metodelor de analiz amortizat, se alege un inel
unidirecional cu elemente de tip T. Un inel nevid este caracterizat printr-un vrf ce
poate fi deplasat prin inel element cu element astfel nct doar elementul de la vrful
inelului este accesibil. Evident, dup parcurgerea tuturor elementelor din inel, vrful
ajunge n poziia iniial. Considerm c operaiile inelului sunt:
void:
T Ring construiete inelul vid.
ins:T T Ring T Ring. ins(e,R) insereaz elementul e la vrful inelului R.
del:T Ring\{void} T Ring. del(R) elimin elementul de la vrful inelului
nevid R. Vrful este poziionat pe urmtorul element, dac acesta exist.
top:T Ring\{void} T. top(R) este elementul de la vrful inelului nevid R.
move:T Ring\{void} T Ring. Prin move(R) vrful inelului nevid R este
deplasat spre dreapta, peste elementul curent.
empty:T Ring bool = {0,1}. empty(R) testeaz dac inelul R este vid.
Descrierea informal de mai sus corespunde urmtoarei specificaii algebrice a
tipului T Ring.
T Ring ::= void | ins(T, T Ring)
top: T Ring \{void} T
move: T Ring\{void} T Ring
del: T Ring\{void} T Ring
empty: T Ring bool
(1)
(2)
(3)
(4)
(5)
(6)

empty(void) = 1
empty(ins(e,X)) = 0
top(ins(e,X)) = e
del(ins(e,X)) = X
move(ins(e,void)) = ins(e,void)
move(ins(e,ins(e',X))) = ins(e',move(ins(e,X)))

Cum putem fi siguri c specificaia corespunde ntr-adevr unui inel


unidirecional? Cu alte cuvinte, cum putem proba corectitudinea specificaiei? O
posibilitate const n alegerea unei proprieti reprezentative inelului i, apoi, n a o
,X
T Ring | empty(X)
verifica folosind specificaia. De exemplu, i
top(movei(X)) = element(i,X), unde element(i,X) rentoarce elementul i mod
size(X) din inelul nevid X. Pentru a nu devia de la subiectul principal discutat analiza
amortizat un asemenea exerciiu este efectuat n seciunea 2.4.5,

Corectitudine i complexitate

Inelul poate fi implementat ca o list circular, iar prelucrarea este banal dac
limbajul de programare folosit lucreaz direct cu pointerii din celulele listei. n acest caz
toate operaiile sunt n (1). S considerm ns c limbajul de programare folosit nu
lucreaz n mod direct cu pointeri ci dispune de tipul T List (list unidirecional cu
elemente de tip T), cu operatorii i specificaia formal de mai jos, unde:
nil este lista vid.
cons(e,L) construiete din lista L o list care are ca prim element e.
head(L) rentoarce elementul de la vrful listei nevide L.
tail(L) rentoarce lista rezultat prin decuparea elementului de la vrful lui L.
null(L) testeaz dac lista L este vid.
T List ::= nil | cons(T, T List)
head: T List\{nil} T
tail: T List\{nil} T List
null: T List bool
(1L)
(2L)
(3L)
(4L)

head(cons(e,L)) = e
tail(cons(e,L)) = L
null(nil) = 1
null(cons(e,L)) = 0

O implementare posibil a tipului T Ring folosind tipul T List consider un inel


nevid ca abstractizarea AbspL,R a unei perechi L,R de liste unidirecionale L i R.
Lista R conine elementele din inel situate ntre vrful curent i "ultimul" element al
inelului, iar L conine elementele, aranjate n ordine invers, aflate ntre poziia iniial
i poziia curent a vrfului inelului. Inelul vid este abstractizat prin Absp(nil,nil).
Reprezentarea este ilustrat n figura 2.8.
vrf
e1

ek

ek+1

L
ek

e1

en

R
ek+1

en

Figura 2.8 Un inel unidirecional reprezentat prin dou liste unidirecionale


Fie inelul X = AbspL,R. Convenim ca lista R s fie vid doar dac inelul X este
vid. O astfel de reprezentare a inelului o vom numi normalizat i poate fi obinut prin
operaia:
(norm) normalizeL,R = if null(R) then nil,reverse(L) else L,R

unde reverse(L) construiete inversa listei L i determin complexitatea normalizrii.

Introducere n analiza algoritmilor

n cazul cel mai defavorabil, complexitatea operaiei reverse(L) este (n), n


fiind numrul de elemente din inel (numrul de elemente din inelul AbspL,nil).
Operaiile inelului presupun un inel cu reprezentare normalizat i conduc la un
inel cu reprezentare normalizat, fiind implementate conform ecuaiilor urmtoare,
numite axiome de implementare:
(1i)
(2i)
(3i)
(4i)
(5i)
(6i)

void = Abspnil,nil
ins(e,AbspL,R) = AbspL,cons(e,R)
del(AbspL,R) = Absp(normalizeL,tail(R))
move(AbspL,R) = Absp(normalizecons(head(R),L),tail(R))
top(AbspL,R) = head(R)
empty(AbspL,R) = null(R)

Este interesant de observat c funcia Absp este definit peste clase de


echivalen ale perechilor L,R. ntr-adevr, n cursul prelucrrilor, se pot obine
implementri diferite dar echivalente ale aceluiai inel.
Spunem c reprezentarea L,R este echivalent cu reprezentarea L',R' a
unui inel, cu alte cuvinte spunem c AbspL,R i AbspL',R' reprezint acelai inel i
scriem AbspL,R = AbspL',R', dac R @ (reverse L) = R' @ (reverse L'),
unde @ reprezint concatenarea listelor. Dac Z i W sunt valori de tipul T List, iar e
este un element de tip T, concatenarea poate fi implementat conform axiomelor:
nil @ Z = Z
cons(e,W) @ Z = cons(e, W @ Z)

Folosind relaia de echivalen


AbspL,R = AbspL',R' R @ (reverse L) = R' @ (reverse L'),

se poate verifica c implementarea conform ecuaiilor de mai sus respect axiomele


din specificarea algebric a tipului T Ring, deci c implementarea este corect. De
exemplu, fie X = AbspL,R i axioma
move(ins(e,ins(e',X))) = ins(e',move(ins(e,X)))

Prin rescrierea celor doi termeni ai axiomei, conform axiomelor tipurilor T Ring,
T List i ecuaiilor de implementare, se ajunge la acelai inel.
move(ins(e,ins(e',X)))
= move(ins(e,ins(e',AbspL,R)))
2i move(ins(e,AbspL,cons(e',R)))
2i move(AbspL,cons(e,cons(e',R)))
4i,1L,2L Absp(normalize cons(e,L),cons(e',R))
norm Abspcons(e,L),cons(e',R)
= X'
ins(e',move(ins(e,X))
= ins(e',move(ins(e,AbspL,R)))

Corectitudine i complexitate

2i ins(e',move(AbspL,cons(e,R)))
4i,1L,2L ins(e',Absp(normalizecons(e,L),R))

Caz 1. R = nil, L = nil


norm ins(e',Abspnil,cons(e,nil))
2i Abspnil,cons(e',cons(e,nil))
= X"

Dar, n acest caz, X' = Abspcons(e,nil),cons(e',nil), iar cons(e',nil)


@ reverse(cons(e,nil)) = cons(e',cons(e,nil)). Deci X' = X".
Caz 2. R nil

norm ins(e',Abspcons(e,L),R)
2i Abspcons(e,L),cons(e',R)
= X'

2.7.2 Analiz de ansamblu


Costul operaiilor del i move este (n) n cazul cel mai defavorabil, unde n
este lungimea inelului, dar cazul cel mai defavorabil nu apare mereu. Dificultatea
stabilirii exacte a complexitii operaiilor rezid n interdependena dintre frecvena
cazurilor defavorabile, cnd normalizarea are loc efectiv, i secvena de operaii
aplicate inelului. Prin urmare o asemenea complexitate exact, absolut, este
imposibil de calculat. Ce se poate calcula este costul mediu al unei secvene oarecare
de operaii. Lund ca operaie critic deplasarea unui element al inelului ntre listele L
i R, un raionament posibil este urmtorul.
Aparent, pornind de la un inel vid, dup o secven S de m operaii oarecare
fiecare element din inel poate fi deplasat ntre L i R de cel mult (m) ori. Deplasarea
L->R are loc n timpul unei normalizri, iar deplasarea R->L are loc n prima faz a
unei operaii move, naintea eventualei normalizri. Inelul poate conine cel mult m
elemente, deci costul celor m operaii este cost(S) m (m)= (m2). Prin urmare,
costul amortizat al unei operaii din cele m este (m2)/m = (m). Totui, acest rezultat
reprezint o margine superioar mult mai larg dect cea real. Normalizrile efective,
deci transferurile L->R nu au loc pentru fiecare operaie din cele m. De asemenea,
dac inelul conine m elemente atunci nici o operaie nu poate fi move sau del.
Pentru o estimare mai exact a costului amortizat al operaiilor din secvena S,
s observm c numrul de deplasri L->R de elemente nu poate fi mai mare ca
numrul operaiilor move din S. ntr-adevr, un element trebuie s fie n lista L pentru a
putea fi transferat n R i numai operaiile move ncarc lista L. De asemenea, numrul
deplasrilor R->L este egal cu numrul operaiilor move din S. Prin urmare, numrul
total de deplasri de elemente ntre listele L i R ale inelului nu poate depi dublul
numrului operaiilor din S. Costul cumulat al acestor deplasri (ca efect al operaiilor
move i del din S) este (2m). La costul deplasrilor de elemente se adaug costul
inserrilor elementelor n R, ca efect al operaiilor ins, costul eliminrilor elementelor

Introducere n analiza algoritmilor

din R, ca efect al operaiilor del i costul operaiilor top i empty. Costul tuturor acestor
operaii este (m). Rezult cost(S)= (m)+
(2m)= (m), iar costul amortizat al unei
operaii a inelului este (m)/m = (1).
Metoda utilizat mai sus pentru a estima costul mediu al unei operaii a inelului
unidirecional poart numele de analiz de ansamblu (n englez metoda este ntlnit
sub denumirea aggregate method). Se urmrete contorizarea execuiilor tuturor
suboperaiilor ce formeaz operaiile unei structuri de date n raport cu lungimea unei
secvene oarecare de astfel de operaii. Metoda calculeaz un singur cost amortizat
(cost mediu al operaiilor unei secvene oarecare de operaii care acoper cazurile cele
mai defavorabile) pentru toate operaiile unui algoritm, chiar dac operaiile au costuri
amortizate diferite.

2.7.3 Metoda creditelor


O analiz amortizat mai fin impune diferenierea costurilor diverselor operaii
efectuate de algoritm. O astfel de analiz poate folosi metoda creditelor (n englez
metoda este ntlnit sub denumirea accounting method).
Presupunem c algoritmul execut o secven de operaii S asupra unei
structuri de date D. Fiecrei operaii op
S i se asociaz un cost amortizat costa(op),
costul real al operaiei fiind notat cost(op). Valoarea costa(op) este costul mediu al
op, cost care acoper cazurile cele mai defavorabile, n timp ce cost(op) poate varia
n funcie de istoria prelucrrii i de elementele prelucrate ale structurii D. Atunci cnd
costa(op) > cost(op) diferena costa(op) - cost(op) reprezint un credit care este
asociat unor elemente ale structurii D, elemente prelucrate de op. Creditul este utilizat
pentru a compensa costul real al acelor operaii op din S care satisfac cost(op) >
costa(op).
Creditul cumulat pentru fiecare element al structurii D trebuie s fie pozitiv n
orice moment de timp. Astfel, se poate garanta c pentru orice secven S de operaii
exist inegalitatea cost(op) costa(op), adic suma costurilor amortizate ale
opS

opS

operaiilor din secven reprezint o limit superioar a costului real al secvenei.


Pentru inelul unidirecional costurile reale ale operaiilor ins, top i empty sunt
(1) i, pentru simplitate, sunt considerate 1. De asemenea, considerm 1 costul unei
operaii de deplasare a unui element ntre listele L i R ale inelului. Costul real pentru
move depinde de starea inelului i variaz ntre 1 i 1+n, unde n este numrul de
elemente din inel. Pentru del costul real este ntre 1 i n. Alocm costurile amortizate:
costa(void)= costa(ins)= costa(del)= costa(top)= costa(empty)=1
costa(move)=2

S asociem fiecrui element e din inel un credit credit(e) astfel nct creditul
iniial s fie 0. Doar operatorii del i move pot s modifice creditul elementelor unui

Corectitudine i complexitate

inel. De exemplu, dup operaia move(X) fr normalizare creditul elementului top(X)


crete cu diferena dintre costa(move)-cost(move(X)), adic cu 1. Distribuia
creditelor elementelor unui inel este precizat de invariantul:
e
L credit(e)=1) (
I(AbspL,R) =def (
e
R credit(e)=0)

Invariantul arat c pentru orice element din inel creditul rmne mereu pozitiv.
n ipoteza n care operaiile ce nu modific inelul nu modific nici creditele elementelor,
iar costurile amortizate asociate operaiilor care modific inelul respect invariantul,
adic
I(void) (
X T Ring I(X) (
op
{ins,del,move} I(op(X))),
putem admite c, pentru orice secven de operaii i pentru orice inel, costul mediu al
unei operaii op este costa(op). Pentru constructorii void, ins, move i del
demonstraia este prin inducie structural.
Propoziia 2.6 Costurile amortizate ale constructorilor inelului AbspL,R menin
invariantul I(AbspL,R).
Caz de baz. X = Abspnil,nil, iar invariantul I(X) este satisfcut banal.
Pas de inducie. S considerm c pentru inelul X = AbspL,R, R
nil, cu n
elemente, invariantul I(X) este satisfcut (ipoteza inductiv). S artm c invariantul
este satisfcut dup orice operaie ins, del sau move aplicat lui X.
Pentru operaia ins(e,X) inelul devine AbspL,cons(e,R). Costul amortizat
costa(ins) este 1 exact ct cost(ins(e,X)) astfel nct credit(e)=0 i, conform
ipotezei inductive, invariantul I(AbspL,cons(e,R)) este satisfcut.
Pentru operaia move(X) = AbspL',R' fie e elementul de la vrful lui X,
anume e = top(X) = head(R).
Caz 1: tail(R)
nil. Operaia move are o singur faz: deplasarea lui e din R n
L, astfel nct L'= cons(e,L), R'= tail(R). Costul real al operaiei move(X) este 1,
iar diferena costa(move)-cost(move(X)) = 2-1 = 1 este adugat creditului
elementului e. Conform ipotezei inductive, naintea operaiei move avem credit(e)=0,
astfel nct credit(e)=1 dup move(X). Invariantul I(AbspL',R') este satisfcut.
Caz 2: tail(R)=nil. Operaia move are dou faze: transferul lui e din R n L i
apoi normalizarea efectiv a inelului, astfel nct L'= nil i R'= reverse(cons(e,L)).
a) Elementul e este mutat din R n L. Ca urmare a ipotezei inductive, creditul lui
e devine credit(e)=1, iar elementele din L au creditul 1. Invariantul
I(Abspcons(e,L),nil este satisfcut dup aceast prim faz.
b) Inelul este normalizat. Toate elementele din cons(e,L) sunt deplasate n
R'. Costul deplasrii unui element e este 1 i este suportat din creditul
credit(e)=1, astfel nct, odat ajuns n R', elementul e are credit(e)=0.
Invariantul I(Abspnil,reverse(cons(e,L))=I(move(X)) este satisfcut.

Introducere n analiza algoritmilor

n cazul (2) exist n-1 elemente n lista L i un singur element n lista R, iar
costul real al operaiei move(X) este 1+n,. Dei costa(move)=2, diferena n-1 este
suportat din creditele elementelor aflate n L.
Pentru del(X) = AbspL',R', notm e = top(X) = head(R). Ca i pentru
move(X) exist dou cazuri.
nil. Operaia del are o singur faz: eliminarea lui e din R.
Caz 1: tail(R)
Rezult L'= L i R'= tail(R). Costul real al operaiei del(X) este 1 exact ct costul
amortizat, deci nu au loc modificri de credite. Conform ipotezei inductive, invariantul
I(AbspL,tail(R)) este satisfcut.

Caz 2: tail(R)=nil. Operaia del are dou faze: eliminarea elementului e din R
i normalizarea efectiv a inelului. Rezult L'=nil i R'= reverse(L).
a) Elementul e este eliminat din R. Operaia cost 1 exact ct costul amortizat
costa(del). Nu au loc modificri de credite i, conform ipotezei inductive,
invariantul I(AbspL,nil) este satisfcut.
b) Inelul este normalizat. Elementele din L sunt deplasate n R'. Costul
deplasrii unui element e este 1 i este suportat din creditul credit(e)=1,
astfel nct, odat ajuns n R', elementul e are credit(e)=0. Invariantul
I(Abspnil,reverse(L))= I(del(X)) este satisfcut.
n cazul (2) costul real al operaiei del(X) este n. Dei costa(del)=1, diferena
n-1 este suportat din creditele celor n-1 elemente aflate n L naintea operaiei. !
Deoarece suma creditelor elementelor din inel este ntotdeauna pozitiv, rezult
c pentru o secven oarecare S de m operaii ce pleac cu un inel vid X avem:
cost(S) =

cost(op)

opS

costa(op)

opS

2m,

deci, cost(S) = (m).


cost(move)
(n)

(1)

costa(move)
S

Figura 2.9 Costul real i costul amortizat pentru operaia move


(n este lungimea maxim a inelului n cursul operaiilor S)
Cu alte cuvinte, costul mediu al unei operaii op a inelului, cost ce acoper
cazurile cele mai defavorabile, este costa(op) = (1), dei costul real poate varia
neuniform aa cum se ilustreaz n figura 2.9.

Corectitudine i complexitate

Analiza de mai sus este independent n raport cu starea iniial X0=

AbspL0,R0 a inelului, cu condiia ca invariantul I(AbspL0,R0) s fie satisfcut.

2.7.4 Metoda potenialului


Metoda potenialului deriv din cea a creditelor prin centralizarea acestora. n loc
de a asocia credite elementelor structurii de date prelucrate de algoritm, putem asocia
un singur credit ntregii structuri de date. n acest caz creditul joac rolul unei energii
poteniale care poate folosi pentru compensarea operaiilor mai costisitoare. Metoda
rezultat este denumit metoda potenialului.
R+, care msoar energia
Structurii de date D i se asociaz o funcie :D
potenial a structurii la un moment dat. Fie S = op1, op2, ..., opm o secven de m
operaii executate de un algoritm asupra structurii D. S notm cu D0 structura iniial,
naintea aplicrii operaiei op1, i cu Di structura rezultat dup aplicarea primelor i
operaii asupra lui D0. De asemenea, notm cu i energia potenial a lui Di.
Di =def opi(opi-1(...op1(D0)...)) = opi(Di-1), i=1,m
i =def (Di), i=0,m

Fie cost(opi) costul real al operaiei opi(Di-1), iar costa(opi) costul


amortizat al operaiei opi relativ la , cost definit prin:
costa(opi) =def cost(opi) + i - i-1, i=1,m

Costul amortizat al operaiei opi(Di-1) adaug costului real variaia de


potenial a structurii de date D, variaie indus de operaie. nsumnd, obinem:
m

i=1

i=1

costa(opi) = (cost(opi) +
Dac m 0 atunci

i i 1) =

i=1

i=1

cost(opi) +

i=1

m 0

costa(opi) cost(opi) i, deoarece costul

secvenei S este suma costurilor operaiilor din S, rezult cost(S)

costa(opi)=

i=1

costa(S). Deoarece dorim pstrarea inegalitii cost(S) costa(S) pentru orice


secven S, implicit, pentru orice m, impunem ca i0 pentru orice i. Cu alte cuvinte,
energia potenial a structurii D la un moment diferit celui iniial trebuie s fie mai mare
dect energia iniial. Pentru cazul particular convenional 0=0, este necesar ca
i0. Aceast ultim inegalitate este natural, din moment ce energia nu poate fi

consumat n lips.

Ca exemplu, s reconsiderm inelul unidirecional reprezentat printr-o pereche


de liste, ca n figura 2.8. Definim funcia asociat inelului X = AbspL,R prin (X) =

10

Introducere n analiza algoritmilor

#L, unde #L desemneaz numrul de elemente din lista L. Funcia de potenial

respect restriciile:
(X) = 0 pentru un inel vid X = Abspnil,nil
(X) 0 pentru un inel oarecare X = AbspL,R

Putem calcula acum costurile amortizate ale operaiilor ce modific inelul X.


Suma acestor costuri pentru o secven de operaii S, aplicat pe un inel iniial vid (sau
pe un inel cu #L=0), constituie o margine superioar a costului real al secvenei. Notm
Xi=AbspLi,Ri inelul X obinut dup a i-a operaie din secvena S.
Presupunnd c ins este a i-a operaie din secvena de operaii S executate
asupra inelului X, anume Xi = ins(e,Xi-1), avem: cost(ins(e,Xi-1)) = 1, Xi =
AbspLi-1,cons(e,Ri-1), i i= #Li= #Li-1= i-1. Rezult,
costa(ins) = cost(ins(e,Xi-1)) + i - i-1 = 1

Presupunnd c move este a i-a operaie din secvena de operaii S, anume


Xi= move(Xi-1), exist dou cazuri posibile.
Caz #Ri-1 > 1. Operaia move(Xi-1) const n transferul primului element din
Ri-1 astfel nct Li=cons(top(Ri-1),Li-1) i Ri=tail(Ri-1).
cost(move(Xi-1)) = 1
i = #Li = #Li-1 +1
i-1 = #Li-1
costa(move) = cost(move(Xi-1)) + i - i-1 = 2

Caz #Ri-1 = 1. Dup transferul unicului element e=top(Ri-1) din Ri-1 are loc
normalizarea efectiv a inelului X'= Abspcons(e,Li-1),nil. Rezult, AbspLi,Ri =
Abspnil,reverse(cons(e,Li-1). Normalizarea inelului X' cost #Li-1+1.
cost(move(Xi-1)) = 1 + cost_normalizare(X') = 1 + #Li-1 + 1
i = #Li = #nil = 0
i-1 = #Li-1
costa(move) = cost(move(Xi-1)) + i - i-1 = 2

Presupunnd c del este a i-a operaie din secvena de operaii S, anume


Xi= del(Xi-1), exist dou cazuri posibile.
Caz #Ri-1 > 1. Operaia del(Xi-1) se limiteaz la eliminarea primului element
din Ri-1. Lista Li-1 nu este modificat.
cost(del(Xi-1)) = 1
i = #Li = #Li-1
i-1 = #Li-1
costa(del) = cost(del(Xi-1)) + i - i-1 = 1

Corectitudine i complexitate

11

Caz #Ri-1 = 1. Dup eliminarea unicului element din Ri-1 are loc normalizarea
inelului X'= AbspLi-1,nil astfel nct AbspLi,Ri = Abspnil,reverse(Li-1).
Normalizarea inelului X' cost #Li-1.
cost(del(Xi-1)) = 1 + cost_normalizare(X') = 1 + #Li-1
i = #Li = #nil = 0
i-1 = #Li-1
costa(del) = cost(del(Xi-1)) + i - i-1 = 1

Evident, pentru operaiile op {top,empty}, care nu modific inelul i, implicit,


conserv potenialul , avem costa(op) = cost(op) = 1. n ceea ce privete cazul
particular void, se asigur (void) = 0, iar costa(void) = cost(void) = 1.
(n)

cost(move)

(1)

Figura 2.10 Costul real al operaiei move i variaia potenialului inelului


n este lungimea maxim a inelului n cursul operaiilor S
n figura 2.10 este ilustrat variaia potenialului inelului n cursul secvenei S.
Curba este n dini de fierstru. Potenialul crete pentru fiecare operaie move
care nu conduce la normalizarea inelului. Pentru o operaie move urmat de
normalizarea inelului cade la 0, energia acumulat fiind folosit pentru deplasarea
elementelor inelului din lista L n R. Iniial, pentru inelul vid =0.
S-au obinut aceleai costuri amortizate ca i n cazul analizei bazate pe credite.
{void, ins, del, move, top, empty},
Deoarece costa(op) = O(1) pentru orice op
costul oricrei secvene S de m operaii pentru inelul unidirecional (iniial vid) este:
cost(S)

costa(opi)

i=1

= (m)

Metoda potenialului a fost aplicat mai sus pentru cazul particular (D0)=0.
Urmtoarea proprietate arat c analiza conduce la aceleai rezultate i pentru
(D0)>
>0 cu condiia ca (Di) (D0), i=1,m.
>0 i (Di) (D0), i=1,m, atunci exist o
Propoziia 2.7 Dac (D0)>
funcie de potenial ' astfel nct:

1. '(D0) = 0 i '(Di) 0, i=1,m


2. Costurile amortizate costa(opi), i=1,m, calculate pentru funcia de
potenial , sunt aceleai ca i costurile amortizate costa'(opi) calculate
pentru '.

12

Introducere n analiza algoritmilor

S construim ' astfel nct '(Di) = (Di) - (D0), i=0,m. Se verific


egalitile:
'(D0) = (D0) - (D0) = 0
'(Di) = (Di) - (D0) 0
costa'(opi) =
=
=
=
!

cost(opi) +
cost(opi) +
cost(opi) +
costa(opi).

'(Di) - '(Di-1)
(Di) - (D0) - (Di-1) + (D0)
(Di) - (Di-1)

Pentru funcia (AbspL,R) = #L din analiza inelului unidirecional, propoziia


(2.7) nu poate fi aplicat deoarece precondiia (Di) (D0) necesar aplicrii nu
>0 arat c inelul nu este vid la
este satisfcut pentru orice i=1,m. ntr-adevr, (D0)>
nceputul operaiilor din secvena S. Este uor de observat c dup o normalizare
efectiv impus de operatorul opi rezult (Di)=0, iar relaia (Di) (D0) nu este
satisfcut.
n cazuri similare cu cel de mai sus, calculul costului secvenei S poate fi
efectuat considernd funcia de potenial:
'(D0) = (D0) > 0
'(Di) = (Di) + (D0) > 0, i=1,m
0, i=1,m. Astfel, potenialul '
unde, de asemenea, impunem restricia (Di)
satisface '(Di) '(D0), pentru i=1,m.
>1 rezult:
Pentru i>
costa'(opi) = cost(opi) + '(Di) - '(Di-1)
= cost(opi) + (Di) - (Di-1)
= costa(opi).

Pentru i=1 obinem:


costa'(op1) = cost(op1) + '(D1) - '(D0)
= cost(op1) + (D1)
cost(op1).

Cu excepia op1, costurile amortizate pentru ' sunt aceleai ca i cele obinute
n cazul funciei de potenial . n ceea ce privete operaia op1, costul ei amortizat
este cel al unei secvene de operaii S' = op1', ..., opq', cu opq' = op1, care aduce
structura de date dintr-o stare cu potenialul 0 n starea D1.1
1 Putem considera op ca operaie compus din prelucrri ce pornesc de la o structur
1

de date cu potenial nul.

Corectitudine i complexitate

13

S observm c funcia ' satisface restriciile impuse de propoziia (2.7), astfel


nct costurile costa' sunt cele calculate pentru funcia de potenial
"(D0) = '(D0)- '(D0) = 0
"(Di) = '(Di)- '(D0) = (Di) 0, i=1,m

cu particularitatea operaiei op1, echivalent secvenei S' de operaii corespunztoare


transformrii de potenial 0 S' (D1).
n concluzie, analiza amortizat folosind " este relevant i pentru , pornind
de la structura D1 pe care s-a executat deja prima operaie. Cu alte cuvinte, analiza
amortizat pentru o structur de date cu potenial iniial 0 (eventual vid), este
relevant i pentru o structur de date aflat n orice stare iniial valid.
n cazul inelului cu starea iniial D0= AbspL0,R0, L0nil, funcia de potenial
modificat este:
'(D0) = #L0
'(Di) = #Li + #L0

Se poate constata c, ignornd prima operaie dintr-o secven de operaii, se


obin costurile amortizate corespunztoare analizei ce pornete de la un inel cu
potenial #L0=0.

14

Introducere n analiza algoritmilor

2.7.5 Verificarea unor proprieti ale inelului


,X
T Ring | empty(X) Prop(i,X), unde
S verificm proprietatea i
Prop(i,X) =def top(movei(X)) = element(i,X)

Proprietatea este reprezentativ unui inel unidirecional i arat c dup i


deplasri succesive ale vrfului unui inel nevid, elementul de la vrf este al i-lea
element din inelul iniial. n acest fel, se precizeaz c deplasarea vrfului pstreaz
ordinea elementelor din inel. Proprietatea folosete urmtorii operatori auxiliari:
- element: (T Ring\{void}) T element(i,X) rentoarce elementul i
mod size(X) din inelul nevid X.
- elm: (T Ring\{void} T elm(i,X) rentoarce elementul din poziia i,
0 i < size(X), din inelul nevid X.
- size: T Ring size(i,X) este numrul de elemente din inelul X.
Pentru a scurta scrierea, adoptm #X ca notaie alternativ a lui size(X).

Extins cu aceti operatori, specificaia tipului T Ring devine:


T Ring ::= void | ins(T, T Ring)
top: T Ring \{void} T
move: T Ring\{void} T Ring
del: T Ring\{void} T Ring
empty: T Ring bool
T
element: (T Ring \{void})
elm: (T Ring\{void}) T
size: T Ring
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9)
(10)
(11)

empty(void) = 1
empty(ins(e,X)) = 0
top(ins(e,X)) = e
del(ins(e,X)) = X
move(ins(e,void)) = ins(e,void)
move(ins(e,ins(e',X))) = ins(e',move(ins(e,X)))
element(i,X) = elm(i mod size(X),X)
elm(0,X) = top(X)
elm((i+1),ins(e,X)) = elm(i,X), pentru i < size(X)
size(void) = 0
size(ins(e,X)) = 1+size(X)

Pentru verificarea Prop(i,X),


demonstrate prin inducie structural.

sunt

utile

urmtoarele

dou

propoziii,

Corectitudine i complexitate

15

Propoziia 2.8 X
T Ring | empty(X) P1(X), cu P1(X)=def #move(X))= #X
Caz de baz. X = ins(e,void).
#move(ins(e,void)) 5 #ins(e,void)

Pas de inducie. X = ins(e,ins(e',X')). Ca ipotez inductiv considerm


adevrat proprietatea e
T P1(ins(e,X')).
#move(ins(e,ins(e',X')))
6 #ins(e',move(ins(e,X')))
11 1+ #move(ins(e,X'))
ip.ind 1+#ins(e,X')
11 2+#X'
#ins(e,ins(e',X'))
11 1+#ins(e',X')
11 2+#X'
!

Propoziia 2.9 i
,X
T Ring | empty(X) P2(i,X), unde
P2(i,X)=def element(i,move(X)) = element(i+1,X)

Caz de baz.
arbitrar.

X = ins(e,void). S verificm P2(i,X), pentru i


ales

element(i,move(ins(e,void)))
5 element(i,ins(e,void))
7 elm(i mod #ins(e,void),ins(e,void))
11,10 elm(i mod 1, ins(e,void))
mod elm(0, ins(e,void))
8,3 e
element(i+1,X)
7 elm((i+1) mod #ins(e,void),ins(e,void))
11,10 elm((i+1) mod 1, ins(e,void))
mod elm(0, ins(e,void))
8,3 e

Pas de inducie. X = ins(e,ins(e',X')). Ca ipotez inductiv considerm c


T P2(i,ins(e,X')), pentru i
este adevrat proprietatea e
ales arbitrar. S
artm c proprietatea P2(i,X) este adevrat. Notm:
LHS = element(i,move(X))
RHS = element(i+1,X)
LHS = element(i,move(ins(e,ins(e',X'))))
6 element(i,ins(e',move(ins(e,X'))))
7,11,P1 elm(i mod (2+#X'),ins(e',move(ins(e,X'))))

16

Introducere n analiza algoritmilor


Caz (a): i mod (2+#X')=0. Atunci, avem (i+1) mod (2+#X') = 1.
LHS = elm(0,ins(e',move(ins(e,X')))) 8,3 e'
RHS =

element(i+1,ins(e,ins(e',X')))
7,11 elm((i+1) mod (2+#X'), ins(e,ins(e',X')))
[(i+1) mod (2+#X') = 1] elm(1, ins(e,ins(e',X')))
9 elm(0,ins(e'X'))
8,3 e'

Caz (b): i mod (2+#X')>


>0. Atunci, i>
>0 i i mod (2+#X')= (i-1) mod (2+#X')+1.
LHS = elm((i-1) mod (2+#X')+1,ins(e',move(ins(e,X'))))
9 elm((i-1) mod (2+#X'),move(ins(e,X')))
[(i-1) mod (2+#X') < 1+#X']
elm(((i-1) mod (2+#X')) mod(1+#X'), move(ins(e,X')))
P1,7 element((i-1) mod (2+#X'), move(ins(e,X')))
ip.ind element((i-1) mod (2+#X')+1, ins(e,X'))
[i mod (2+#X') = (i-1) mod (2+#X')+1]
element(i mod (2+#X'), ins(e,X'))
Caz (b1): i mod (2+#X') = 1+#X'
LHS =

element(1+#X', ins(e,X'))
7 elm((1+#X') mod ins(e,X'), ins(e,X'))
11 elm((1+#X') mod (1+#X'), ins(e,X'))
mod elm(0, ins(e,X'))
8,3 e

Totodat, i mod (2+#X') = 1+#X' (i+1) mod (2+#X') = 0


RHS =

element(i+1, ins(e,ins(e',X')))
7,11 elm((i+1) mod (2+#X'), ins(e,ins(e',X')))
[(i+1) mod (2+#X') = 0] elm(0, ins(e,ins(e',X')))
8,3 e

Caz (b2): i mod (2+#X') < 1+#X'


LHS = element(i mod (2+#X'), ins(e,X'))
7,11 elm((i mod (2+#X')) mod (1+#X'), ins(e,X'))
mod elm(i mod (2+#X'), ins(e,X'))
9,[0 < i mod (2+#X') < 1+#X'] elm(i mod (2+#X')-1, X')
RHS = element(i+1, ins(e,ins(e',X')))
7,11 elm((i+1) mod (2+#X'), ins(e,(ins(e',X')))
[(i+1) mod (2+#X') = (i mod (2+#X'))+1]
elm((i mod (2+#X'))+1, ins(e,(ins(e',X')))
9 elm(i mod (2+#X'), ins(e',X'))
9,[0 < i mod (2+#X') < 1+#X'] elm(i mod (2+#X')-1, X')
!

Corectitudine i complexitate

17

Propoziia 2.10 Exist proprietatea i


,X
T Ring |
empty(X) Prop(i,X),
unde
Prop(i,X)=def top(movei(X)) = element(i,X).

Demonstraia este prin inducie dup i.


Caz de baz. i=0.
top(move0(X)) = top(X)
element(0,X)
7 elm(0 mod #X,X)
mod elm(0,X)
8 top(X)
T Ring|
Pas de inducie. i
0. Ipoteza inductiv este X
empty(X)Prop(i,X).
S artm c Prop(i+1,X) este adevrat, adic
top(movei+1(X)) = element(i+1,X)
top(movei+1(X)) = top(movei(move(X)))
ip.ind element(i,move(X))
P2 element(i+1,X)

2.7.6 O implementare Haskell a inelului


Dei codificarea direct ntr-un limbaj de programare funcional a
specificaiilor tipurilor de date i implementrilor abstracte depete cadrul acestei
cri, o incursiune superficial i succint n acest domeniu este interesant. Este
scopul acestei seciuni care prezint:

Codificarea Haskell [Tho 96] a specificaiei T Ring.


Implementarea efectiv a inelului conform T Ring = AbsT List, T List.
O aplicaie a inelului pentru sortarea unei liste de chei.

Programele de mai jos corespund aproape ad-litteram specificaiei T Ring sau


ecuaiilor de implementare i, evident, sunt executabile. n particular, programul
corespunztor specificaiei T Ring poate fi considerat ca o implementare "abstract" a
inelului. Totui, n programele Haskell apar urmtoarele diferene minore sau variante
de notaie n raport cu textul din carte:
Program Haskell

Specificaie T Ring

Ring t
e:l
[]
(f x)

T Ring
cons(e,l)
nil (lista vid)
f(x)

18

Introducere n analiza algoritmilor

Rescrierea Haskell a specificaiei inelului


module T_Ring where
-- Constructorii de baz: Void i Ins
-- Limbajul impune nume ce ncep cu litere mari
data Ring t = Void
| Ins (t, Ring t) deriving (Eq,Show)
-- Funcii corespunztoare constructorilor de baz, utile
-- pentru compatibilitate deplin cu implementarea inelului
void = Void
ins(e,x) = Ins(e,x)
-- Axiomele operatorilor (signaturile sunt sintetizate automat)
empty(Void) = True
empty(Ins(_,_)) = False
top(Ins(e,_)) = e
del(Ins(_,x)) = x
move(Ins(e,Void)) = Ins(e,Void)
move(Ins(e,Ins(e',x))) = Ins(e',move(Ins(e,x)))
-- Axiomele operatorilor necesari proprietilor P1,P2 i Prop
element(i,x) = elm(i `mod` size(x), x)
elm(0,x) = top(x)
elm(i+1,Ins(_,x)) = elm(i,x)
size(Void) = 0
size(Ins(_,x)) = 1+size(x)
-- Proprietatile P1, P2 i Prop din seciunea 2.7.5, unde
-- move_i(n,x) este move aplicat de n ori inelului x
p1 x = size(x) == size(move(x))
p2(i,x) = element(i,move(x)) ==
prop(i,x) = top(move_i(i,x)) ==
where move_i(0,x) =
move_i(i+1,x)

element(i+1,x)
element(i,x)
x
= move_i(i,move(x))

-- Funcie care construiete un inel cu cheile unei liste


make_ring [] = Void
make_ring (e:l) = Ins(e,make_ring l)
-- Un inel
x = make_ring [1,2,3,4,5,6,7,8]

Aplicaiile p1(x), p2(i,x) i prop(i,x) rentorc valoarea True pentru orice i


0
si orice inel nevid x.

Corectitudine i complexitate

19

Codificarea Haskell a implementrii inelului


module Ring where
-- O implementare a tipului T Ring in Haskell, ca o pereche de liste
-- Reprezentarea inelului ca pereche de liste cu elemente de tip t
data Ring t = Abs([t],[t]) deriving (Eq,Show)
normalize(l,r) = if r==[] then ([],(reverse l)) else (l,r)
-- Ecuaiile de implementare a operatorilor inelului
void = Abs([],[])
ins (e,Abs(l,r)) = Abs(l,e:r)
del (Abs(l,r)) = Abs(normalize(l,(tail r)))
move (Abs(l,r)) = Abs(normalize((head r):l, (tail r)))
top (Abs(l,r)) = head r
empty (Abs(l,r)) = r == []
-- Axiomele operatorilor necesari proprietilor P1,P2 i Prop
size(x) = if empty(x) then 0 else 1+size(del(x));;
elm(0,x) = top(x)
elm(i+1,x) = elm(i,del(x))
element(i,x) = elm(i `mod` size(x), x)
{Axioma elm(i+1,ins(e,x))) = elm(i,x) este rescrisa n stilul
elm(i+1,y) = elm(i,del(y)) folosind schimbarea de variabil
y = ins(e,x) => x = del(y).
La fel s-a procedat i pentru axioma size(ins(e,x)) = 1+size(x)
scris size(x) = 1+size(del(x))
-}
-- Proprietatile P1, P2 i Prop din seciunea 2.7.5, unde
-- move_i(i,x) este move aplicat de i ori inelului x
p1 x = size(x) == size(move(x))
p2(i,x) = element(i, move(x)) == element(i+1,x)
prop(i,x) = top(move_i(i,x)) == element(i,x)
move_i(0,x) = x
move_i(i+1,x) = move_i(i,move(x))
-- Funcie care construiete un inel cu cheile unei liste
make_ring [] = void
make_ring (e:l) = ins(e,make_ring l)
-- Un inel
x = make_ring [1,2,3,4,5,6,7,8]
0
Aplicaiile p1(x), p2(i,x) i prop(i,x) rentorc valoarea True pentru orice i
i orice inel nevid x. Evident, din moment ce implementarea respect axiomele
specificaiei T Ring, ea conserv i proprietile inelului.

20

Introducere n analiza algoritmilor

O aplicaie: sortare pe baz de inel


Sortarea unei liste unidirecionale folosind un inel de tip T Ring se aseamn cu
sortarea prin inserie direct a unui vector. Pentru simplitate, considerm sortarea
nedescresctoare a unei liste cu chei ntregi, deci presupunem c tipul generic T din
specificaiile T List i T Ring este particularizat la tipul de date int.
O variant simpl de sortare a unei liste nevide l const n construirea unui nou
inel sortat prin inseria elementului head(l) ntr-un inel sortat n aceeai manier i
care conine elementele listei tail(l). Evident, pentru o list vid, inelul sortat este
vid. Operaia de baz a sortrii este
put: int int Ring int Ring

i satisface axiomele
(p1) put(e,void) = ins(e,void)
(p2) put(e,ins(e',X)) = if e < e' then ins(e,ins(e',X))
else ins(e',put(e,X))

S artm c, pentru X
int Ring deja sortat nedescresctor, put(e,X)
produce un inel sortat nedescresctor. Pentru c avem nevoie de formalizarea noiunii
de inel sortat nedescresctor, definim urmtoarele predicate:
ord: int Ring bool i
min: int (int Ring) bool

astfel nct:
(o1) ord(void) = 1
(o2) ord(ins(e,X)) = min(e,X) ord(X)
(m1) min(e,void) = 1
(m2) min(e,ins(e',X)) = e e' min(e,X)

De asemenea, considerm adevrate proprietile


X
int Ring, e
int,e'
int P'(e,e',X)
X
int Ring, e
int,e'
int P"(e,e',X)

unde,
P'(e,e',X) =def min(e,put(e',X)) = e e' min(e,X)
P"(e,e',X) =def e e' min(e',X) min(e,X)

Demonstraiile sunt prin inducie structural, fiind lsate ca exerciiu.


Folosind ord, proprietatea esenial pe care se bazeaz procesul de sortare
int Ring, e
int P(e,X), cu
poate fi formulat X
P(e,X) =def ord(X) ord(put(e,X))

Corectitudine i complexitate

21

Propoziia 2.11 X
int Ring P(X). Demonstraia este prin inducie structural.
Caz de baz: X = void. S alegem e
T arbitrar.
P(e,void) = ord(void) ord(put(e,void))
o1 1 ord(put(e,void))
p1 1 ord(ins(e,void))
o2 1 min(e,void) ord(void)
m1,o1 1 1
= 1

Pas de inducie: X = ins(e',X'), unde e'


int i X'
int Ring sunt valori alese
arbitrar. Ca ipotez inductiv, considerm adevrat proprietatea P(e,X') pentru
e
int ales arbitrar. S artm c proprietatea P(e,X) este adevrat, anume c:
ord(ins(e',X')) ord(put(e,ins(e',X')))

Dac termenul ord(ins(e',X')) este fals, implicaia este adevrat banal. S


considerm c ord(ins(e',X')) este adevrat. Atunci, conform axiomei (o2) avem
urmtoarele concluzii:
(c1) min(e',X') = 1
(c2) ord(X') = 1

Pentru ca implicaia P(e,X) s


ord(put(e,ins(e',X'))) s fie adevrat.

fie

adevrat

trebuie

ca

Caz 1. e < e'


ord(put(e,ins(e',X')))
p2 ord(ins(e,ins(e',X')))
o2 min(e,ins(e',X')) ord(ins(e',X'))
m2 e e' min(e,X') ord(ins(e',X'))
Caz 1, c1, P"(e,e',X')
ord(ins(e',X'))2
ipotez 1

Caz 2. e e'
ord(put(e,ins(e',X')))
p2 ord(ins(e',put(e,X')))
o2 min(e',put(e,X')) ord(put(e,X'))
ip.induct. P(e,X'), c2 min(e',put(e,X'))3
P'(e',e,X') e' e min(e',X')
Caz 2, c1 1
!

2 Termenul min(e,X') este adevrat conform implicaiei P"(e,e',X')


3 Termenul ord(put(e,X')) este adevrat conform implicaiei P(e,X')

termenul

22

Introducere n analiza algoritmilor

Considernd lista de sortat l = cons(l1,cons(l2,...,cons(ln,nil)...)),


atunci, prin inducie dup n i conform propoziiei (2.11), inelul
r = put(l1,put(l2,...,put(ln,void)...)

rezult sortat nedescresctor. Funcia care care construiete inelul r este:


ring_sort: int List int Ring
ring_sort(nil) = void
ring_sort(cons(e,L)) = put(e,ring_sort(L))

Dac dorim ca rezultatul sortrii s fie o list, inventm o funcie care descarc
elementele unui inel (indiferent de tipul elementelor) ntr-o list iniial vid.
ring_to_list: T Ring T List
ring_to_list(void) = nil
ring_to_list(ins(e,X)) = cons(e,ring_to_list(X))

n final, funcia de sortare este reprezentat de compunerea funciilor


ring_sort i ring_to_list:
sort: int List int List
sort L = (ring_to_list ring_sort)(L)
= ring_to_list(ring_sort(L))

Transcrierea Haskell a sortrii, impune modificarea axiomelor funciilor put i


ring_to_list.4 Prima axiom a funciei put este transformat prin schimbarea de
variabil x = void, impunnd restricia empty(x). Cea de a doua axiom a lui put
este transformat folosind schimbarea de variabil x = ins(e',X) i observnd, pe
baza axiomelor din specificaia inelului, c: e' = top(x) i X = del(x). Se obine:
| ins(e,void), dac empty(X)
put(e,X) = | ins(e,X), dac empty(X) e < top(X)
| ins(top(X),put(e,del(X))), dac empty(X) e top(X)
Similar, sunt transformate i axiomele funciei ring_to_list:
| nil, dac empty(X)
ring_to_list(X) = |

| cons(top(X),ring_to_list(del(X)))
4 Motivul l constituie definirea constructorilor void i ins ca funcii implementate pe
baza constructorului Abs. Haskell nu accept ca parametrii formali ai funciilor s fie specificai
n forma unor aplicaii de funcii, aa cum cer axiomele nemodificate ale lui put i
ring_to_list. Totodat, codificarea din modulul RingSort are un avantaj: funcioneaz
corect cu ambele implementri ale inelului, conforme modulelor T_Ring i RingImpl.

Corectitudine i complexitate

23

ntr-o prim variant, codificarea Haskell a sortrii urmrete ndeaproape


specificarea funciei sort.
module RingSort where
import RingImpl
sort l = (ring_to_list . ring_sort) l
where -- f . g este compunerea lui f cu g
ring_sort [] = void
ring_sort (e:l) = put(e,ring_sort(l))
put(e,x)
| empty(x) = ins(e,void)
| e < top(x) = ins(e,x)
| otherwise = ins(top(x),put(e,del(x)))
ring_to_list x
| empty(x) = []
| otherwise = (top x):(ring_to_list (del x))

O variant mai sofisticat folosete o prelucrare interesant, dar comun n


limbajele de programare funcionale. Prelucrarea corspunde urmtoarei funcii:
foldr: ((T T') T') T' (T List) T'
foldr(f,X,nil) = X
foldr(f,X,cons(e,L)) = f(e,foldr(f,X,L))

Prin urmare, aplicaia foldr(put,void,l), unde l = cons(l1,cons(l2,...,


cons(ln,nil)...)), este echivalent cu put(l1,put(l2,...,put(ln,void)...),
adic are efectul ring_sort(l).
module RingSort where
import RingImpl
sort l = ring_to_list(foldr put void l)
where
put e x -- vezi comentariul5
| empty(x) = ins(e,void)
| e < top(x) = ins(e,x)
| otherwise = ins(top(x), put e (del x))
ring_to_list x
| empty(x) = []
| otherwise = (top x):(ring_to_list (del x))

5 foldr cere ca put s fie o funcie binar. n Haskell, put(e,x) definete o funcie
cu un singur parametru din mulimea produs int int Ring, n timp ce put e x descrie o
funcie binar cu primul parametru de tip int i al doilea parametru de tip int Ring. Diferena
este mai subtil: o funcie binar poate fi aplicat parial. Aplicarea asupra primului parametru
produce o funcie unar care ateapt cel de al doilea parametru. Din program, se vede c
nsi foldr este o funcie ternar care are proprieti similare.

24

Introducere n analiza algoritmilor


La ncrcarea i execuia programului, se poate obine un rezultat de forma:
RingSort> sort [5,1,2,7,1,2,5,6,4]
[1,1,2,2,4,5,5,6,7] :: [Integer]

Modulele Haskell de mai sus implementeaz mai mult dect sortarea unei liste
de ntregi. Ele descriu sortarea unei liste cu elemente de orice tip peste care este
definit o relaie de ordine. Generalitatea este vizibil din signatura Haskell a funciei
sort, sintetizat automat, anume:
RingSort> :type sort
sort :: Ord t => [t] -> [t]

Signatura arat c tipul t trebuie s fac parte din clasa Ord, clasa tipurilor
peste care este definit o relaie de ordine. Astfel, se poate scrie:
RingSort> sort [True,False]
[False,True] :: [Bool]
RingSort1> sort [2.1,3.0,3.14,0.1,4.5]
[0.1,2.1,3.0,3.14,4.5] :: [Double]

Complexitatea amortizat a sortrii, anume C(n) = T(n) + D(n) + R(n), unde n


este numrul de chei din lista de sortat, ine cont de complexitatea T(n) a comparrii
cheilor, de complexitatea amortizat D(n) a operaiilor del efectuate n cursul sortrii
i de complexitatea amortizat R(n) a descrcrii inelului sortat n lista rezultat. La
inseria celei de a i-a chei n inel se efectueaz cel mult i-1 comparaii, iar lungimea
secvenei de operaii del este i. Descrcarea inelului implic o secven de n operaii
del, celelalte operaii ale descrcrii avnd complexitate (1). Deci,
T(n) (1)

(i

i=1

1), D(n) =

(i) i

i=1

R(n) = (n)

Rezult C(n) = (n2).

Comentarii
Coninutul seciunii 2.7.6 depete cadrul strict al analizei algoritmilor, fiind la
intersecia urmtoarelor domenii: metode formale, programare funcional, analiza
algoritmilor. Dar morala este vizibil i important: este mai sigur i, n unele cazuri,
mai uor s se dezvolte teoretic un algoritm corect dect s fie construit un algoritm
"intuitiv" care, ulterior, trebuie verificat. Totodat, dezvoltarea elaborat, pornind de la
specificaii, poate salva timp i efort n procesul implementrii algoritmului i validrii
programului. Concluzia capt greutate mai ales pentru aplicaiile critice, acolo unde o
anomalie a algoritmului poate fi extrem de costisitoare.
Cine dorete s afle mai mult despre Haskell poate consulta [Tho 96] i adresa
http://www.haskell.org, unde se gsesc medii de programare Haskell, inclusiv
documentaie Haskell (manual de referin).

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