This is an old revision of the document!


1. Stack

Naiv: La un momnt dat pot fi k elemente in stack, deci cea mai costisitoare operatie va fi mpop cu complexitate temporala O(k). Daca avem n operatii in secventa (avem deci $ n \leq k $ ), vom avea maxim $ n * O(k) = O(n^2) $ . Dar totusi nu putem face atatea $ mpop(k) $ , pentru ca nu avem elemente.

Pentru a putea efectua un $ pop $ , operatia trebuie precedata in secventa $ S $ de un push.

Pentru a putea efectua un $ mpop(k) $ , operatia trebuie precedata in secventa $ S $ de $ k $ operatii push.

Worst-Case: Cate elemente pot fi adaugate si eliminate maxim intr-o secventa de k operatii? * se pot adauga maxim $ (k-1) $ elemente si se pot elimina cu un $ mpop(k-1) $ la final

1.1. Aggregate method

$ pop $ si $ push $ au cost $ 1 $, $ mpop $ are cost $ k $.

$ cost(S) = (k-1) * 1 + (k - 1) = 2k - 2 $

Deci, pentru o singura operatie, avem: $ cost(op) = cost(S) / k = (2k - 2) / k \leq 2 \Rightarrow cost(op) = 2 $

1.2. Banking method

Pentru fiecare operatie push, trebuie sa avem in vedere un viitor $ pop $ . Operatiile $ push $ vor creste creditul, iar operatiile $ pop $ si $ mpop $ il vor scadea.

Alegem:
$ \hat(c_{push}) = 2 $
$ \hat(c_{pop}) = 0 $
$ \hat(c_{mpop}) = 0 $

Aratam ca: $ cost(S) \leq \sum_{i=1}^{n}\hat{c_i} $ .
$ cost(S) = 2k - 2 $ (am vazut anterior)
$ \sum_{i=1}^{n}\hat{c_i} = 2 * (k-1) + 0 * 1 = 2k - 2 $

1.3. Potential method

Fie $ D_k $ starea dupa k operatii. Starea initiala cand stiva e goala este $ D_0 $ . Definim o functie ne-negativa de potential $ \Phi : States \rightarrow ℕ $

Notand costurile amortizate ale unei operatii arbitrare cu $ \hat(c_{i}) $ si costul sau real cu $ c_i $ , avem de aratat ca:
$ \sum_{i=1}^{n}{c_i} \leq \sum_{i=1}^{n}{\hat{c_i}} $

Stim ca: $ \hat{c_i} = c_{i} + \Phi(D_i) - \Phi(D_{i-1}) $

Deci: $ \sum_{i=1}^{n}{\hat{c_i}} = \sum_{i=1}^{n}{c_i} + \Phi(D_n) - \Phi(D_0) $

Acem de ales $ \Phi $ asftel incat $ \Phi(D_0) \leq \Phi(D_n) $ .

$ \Phi(D_0) = 0 $ (mereu)

Daca in stiva avem $ m $ elemente, acestea au “potentialul” de a fi scoase ulterior cu k operatii $ pop $ sau $ mpop(m) $ :
$ \Phi(D) = m $

Calculam costul amortizat al fiecarei operatii:
$ \hat(c_{push}) = c_{push} + \Phi(D_i) - \Phi(D_{i-1}) = c_{push} + (m + 1) - m = c_{push} + 1 = 1 + 1 = 2 $
$ \hat(c_{pop}) = c_{pop} + \Phi(D_i) - \Phi(D_{i-1}) = c_{pop} + (m - 1) - m = c_{pop} - 1 = 1 - 1 = 0 $
$ \hat(c_{mpop(k)}) = c_{mpop(k)} + \Phi(D_i) - \Phi(D_{i-1}) = c_{mpop(k)} + (m - k) - m = c_{mpop(k)} - k = k - k = 0 $

2. Heap

2.1. Aggregate Method

Fie $ S $ o secventa de $ n $ inserari intr-un heap gol. Pentru a simplifica analiza, dar fara a influenta rezultatul, vom presupune ca $ n = 2^k $.

Pe nivelul $ log(n) $ avem 1 element. … Pe nivelul 3 avem n/8 elemente. Pe nivelul 2 avem n/4 elemente. Pe nivelul 1 avem n/2 elemente.

Ca un nod sa ajunga de pe ultimul nivel (aici nivel $ 1 $ pentru a face calculele usoare) pana la unul din nivelele superioare, avem nevoie de: - nivel $ log(n) $ - $ log(n) - 1 $ swaps - … - nivel $ 3 $ - $ 2 $ swaps - nivel $ 2 $ - $ 1 $ swaps - nivel $ 1 $ - $ 0 $ swaps

Deci costul total pentru $ n $ inserari e format din costul de creare al unui nou nod, $ 1 $ insumat cu numarul de swaps necesare pentru a aduce toate nodurile pe pozitiile actuale este:

$ cost(S) = 1 * n + \sum_{i=1}^{log(n)}{nodes(i) * swaps(i)} = $
$ = n + \sum_{i=1}^{log(n)}{n/(2^i) * (i - 1)} = $
$ \leq n + n \sum_{i=1}^{\infty}{(i - 1)/(2^i)} $
$ \leq n + n = 2n $
(puteti folosi inductie pentru acea suma sau https://www.wolframalpha.com/input?i=%5Csum_%7Bi%3D1%7D%5E%7Binf%7D%7B%28i+-+1%29%2F%282%5Ei%29%7D+)

Deci, costul uni singur insert este:
$ cost(op) = cost(S) / n = 2 $

2.2. Accounting Method

Pentru fiecare $ insert $, avem nevoie sa luam in considerare:

  1. costul de creare al unui nou nod = $ 1 $
  2. un potential swap cu parintele = $ 1 $

$ \hat(c_{insert}) = 2$

2.3. Potential Method

Fie starile $ D_i $ = starea heap-ului dupa $ i $ operatii $ insert $

Definim o functie ne-negativa de potential $ \Phi : States \rightarrow ℕ $
$ \Phi(D_0) = 0 $
$ \Phi(D_i) = $ numarul de valori in heap

Calculam costul amortizat intr-un caz simplu, cand nodul nu trebuie interschimbat cu parintele:
$ \hat{c_i} = c_{i} + \Phi(D_i) - \Phi(D_{i-1}) = 1 + i - (i - 1) = 2 $

Aratam acum ca acest cost a fost ales corect, demonstrand inegalitatea
$ sum_{i=1}^{n}{c_i} \leq \sum_{i=1}^{n}{\hat{c_i}} $

Am aratat anterior ca $ \sum_{i=1}^{n}{c_i} \leq 2n $, iar $ \sum_{i=1}^{n}{\hat{c_i}} = 2n $.

3. Binary Counter

3.1. Aggregate method

Bitul 0 se schimba la fiecare operatie.
Bitul 1 se schimba la fiecare $ 2 $ operatii.
Bitul 2 se schimba la fiecare $ 4 $ operatii.

Bitul 2 se schimba la fiecare $ 2^k $ operatii.

Intr-o secventa $ S $ de $ n $ operatii $ increment $, numarul total de modificari de biti este:
$ cost(S) = n + n/2 + n/(2^2) + \ldots + n/(2^k) \leq n / (1 - 1/2) = 2n $

Deci, costul amortizat al unei singure operatii de increment este:

$ cost(op) = cost(S) / n = 2n / n = 2 $

3.2. Accounting method

Costul real al unei operatii este numarul de biti modificati.

Costul amortizat trebuie sa contina:

  1. o schimbare a unui bit din 0 in 1
  2. o schimbare ulterioara a bitului din 1 in 0

$ \hat(c_{increment}) = 2$

3.3. Potential method

Fie starile $ D_i $ = starea contorului dupa $ i $ operatii $ increment $

Definim o functie ne-negativa de potential $ \Phi : States \rightarrow ℕ $
$ \Phi(D_0) = 0 $
$ \Phi(D_i) = $ numarul de biti de $ 1 $ din contor dupa $ i $ operatii $ increment $

Presupunand ca operatia $ i $ reseteaza $ k_i $ biti de 1, costul real al operatiei devine $ c_i = 1 + k_i $.

Stim ca $ \hat{c_i} = c_{i} + \Phi(D_i) - \Phi(D_{i-1}) $

Calculam $ \hat{c_i} $ pe un caz simplu: $ 000000 \rightarrow 000001 $
$ \hat{c_i} = c_{i} + \Phi(D_i) - \Phi(D_{i-1}) = 1 + 1 - 0 = 2 $

Aratam ca $ \sum_{i=1}^{n}{c_i} \leq \sum_{i=1}^{n}{\hat{c_i}} $
$ \sum_{i=1}^{n}{c_i} = 2n $ (am vazut mai devreme la metoda agregarii)
$ \sum_{i=1}^{n}{\hat{c_i}} = n * \hat{c_i} = 2n $