Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
aa:lab:sol:3 [2025/10/19 02:29] andreidarlau04 deletion cu toate metodele |
aa:lab:sol:3 [2025/10/19 21:59] (current) andreidarlau04 [Algebraic Data Types] |
||
|---|---|---|---|
| Line 41: | Line 41: | ||
| Din (1) si (2) => ĉ<sub>i</sub> = T(n) / n = (n + n) / n = 2. | Din (1) si (2) => ĉ<sub>i</sub> = T(n) / n = (n + n) / n = 2. | ||
| + | |||
| + | |||
| + | === ArrayList - cazul generic === | ||
| + | |||
| + | Fie capacitatea initiala = 1, c<sub>i</sub> = costul inserarii, c<sub>d</sub> = costul stergerii. | ||
| + | |||
| + | Stim ca: | ||
| + | * c<sub>i</sub> = 1 pentru cazul fara copiere | ||
| + | * c<sub>i</sub> + m cazul pentru copiere si inserare | ||
| + | * c<sub>d</sub> = 1 pentru cazul fara copiere | ||
| + | * c<sub>d</sub> + m pentru cazul stergerii si copierii | ||
| + | * n<sub>final</sub> = k - p numarul final de elemente (elemente inserare - elemente sterse) | ||
| + | * nr<sub>operatii</sub> = k + p | ||
| + | |||
| + | => ĉ<sub>i</sub> = C<sub>total</sub> / (k + p) = (C<sub>ins</sub> + C<sub>del</sub>) / (k + p) | ||
| + | |||
| + | Am stabilit precedent ca: | ||
| + | * costul tuturor copierilor la inserare este de 2k | ||
| + | * costul tuturor inserarilor efective este k | ||
| + | * => C<sub>ins</sub> = 3k | ||
| + | |||
| + | De asemenea: | ||
| + | * costul tuturor copierilor la stergere este de p | ||
| + | * costul tuturor stergerilor efective este tot p | ||
| + | * => C<sub>del</sub> = 2p | ||
| + | |||
| + | => ĉ<sub>i</sub> = (3k + 2p) / (k + p) | ||
| + | |||
| + | Interpretare: | ||
| + | * pentru p = 0, avem ĉ<sub>i</sub> = 3 (adevarat, asta este costul doar inserarilor) | ||
| + | * pentru k = 0 (presupunem ca avem deja un array), ĉ<sub>i</sub> = 2 (adevarat, costul stergerii) | ||
| + | * pentru k = p, avem ĉ<sub>i</sub> = 2.5 | ||
| + | * => costul amortizat este mai apropiat de 3 pentru mai multe inserari, dar mai apropiat de 2 pentru mai multe stergeri. | ||
| ==== Metoda bancherului ==== | ==== Metoda bancherului ==== | ||
| Line 47: | Line 80: | ||
| (pentru insertion: 3 bani -> 1 inserare, 1 banut atribuit inseratiei curente, 1 banut atribuit altei inseratii din bucata copiata precedent) | (pentru insertion: 3 bani -> 1 inserare, 1 banut atribuit inseratiei curente, 1 banut atribuit altei inseratii din bucata copiata precedent) | ||
| - | Idee de rezolvare: impartim array-ul in 2 bucati, bucata care se va copia la resize iar bucata care se va sterge fara impact. Cand facem o stergere, avem cost 1 pentru stergerea efectiva, dar atribuim un banut pentru copiere ulterioara. Astfel, la timpul unui resize, vom avea banutii exacti necesari pentru copiere. | + | Idee de rezolvare: impartim array-ul in 2 bucati: |
| + | * bucata care se va copia = elementele care raman dupa stergeri | ||
| + | * bucata elementelor care se sterg. | ||
| + | Pentru fiecare operatie de stergere (cost 1), "plasam" un banut catre prima bucata a array-ului (cea care se va copia). In acest fel, la momentul copierii, fiecare element are deja banutul pregatit care ii acopera costul. Astfel, nu mai trebuit platit un cost suplimentar pentru copiere. | ||
| ==== Metoda potentialelor ==== | ==== Metoda potentialelor ==== | ||
| Line 62: | Line 98: | ||
| * c<sub>i</sub> = 1 | * c<sub>i</sub> = 1 | ||
| * ΔΦ = Φ(n - 1, m) - Φ(n, m): | * ΔΦ = Φ(n - 1, m) - Φ(n, m): | ||
| - | * caz 1, n >= 2m: ΔΦ = 2n - 2 - m - 2n + m = -2 => ĉ<sub>i</sub> = -1 | + | * caz 1: n > m/2 => ΔΦ = (2(n - 1) - m) - (2n - m) = -2 |
| - | * caz 2, n < m: ΔΦ = m/2 - n - (m/2 - n - 1) = 1 => ĉ<sub>i</sub> = 2 | + | * caz 2: n = m/2 => ΔΦ = (m/2 - (n - 1)) - (2n - m) = 1 + 3m/2 - 3n, dar n = 3m/2 => ΔΦ = 1 + 3m/2 - 3m/2 = 1 |
| + | * caz 3: n < m/2 => ΔΦ = (m/2 - (n - 1)) - (m/2 - n) = 1 | ||
| Aflam ca pentru un load factor de peste 1/2 (suntem aproape de capacitatea maxima) avem cost amortizat -1, iar 2 daca ne apropiem de injumatatire. | Aflam ca pentru un load factor de peste 1/2 (suntem aproape de capacitatea maxima) avem cost amortizat -1, iar 2 daca ne apropiem de injumatatire. | ||
| + | |||
| + | <note important>In operatiile de analiza amortizata, noi luam drept cost amortizat costul operatiilor mai "scumpe", neluand in calcul operatiile "ieftine", deci ĉ<sub>i</sub> = 2 in acest caz, nu -1. </note> | ||
| 2. Cazul stergerii in care capacitatea se schimba: | 2. Cazul stergerii in care capacitatea se schimba: | ||
| Line 72: | Line 111: | ||
| * c<sub>i</sub> = 1 + n (deletion + copiere) | * c<sub>i</sub> = 1 + n (deletion + copiere) | ||
| * ĉ<sub>i</sub> = 1 + n + (1 - n) = 2 | * ĉ<sub>i</sub> = 1 + n + (1 - n) = 2 | ||
| + | |||
| + | ===== Algebraic Data Types ===== | ||
| + | |||
| + | 1. <code> | ||
| + | typedef struct list { | ||
| + | int e; | ||
| + | struct list *next; | ||
| + | } *List; | ||
| + | |||
| + | List Void() { | ||
| + | return NULL; | ||
| + | } | ||
| + | |||
| + | List Cons(int e, List list) { | ||
| + | List newElem = (List)malloc(sizeof(struct list)); | ||
| + | newElem->e = e; | ||
| + | newElem->next = list; | ||
| + | |||
| + | return newElem; | ||
| + | } | ||
| + | </code> | ||
| + | 2. | ||
| + | <code> | ||
| + | Size(Void) = 0 | ||
| + | Size(Cons(e, L)) = 1 + Size(L) | ||
| + | </code> | ||
| + | <code> | ||
| + | Add(Void, x) = Cons(x, Void) | ||
| + | Add(Cons(y, L), x) = Cons(y, Add(L, x) | ||
| + | </code> | ||
| + | <code> | ||
| + | Append(Void, L) = L | ||
| + | Append(Cons(x, L1), L2) = Cons(x, Append(L1, L2)) | ||
| + | </code> | ||
| + | <code> | ||
| + | Reverse(Void) = Void | ||
| + | Reverse(Cons(x, L)) = Append(Reverse(L), Cons(x, Void)) | ||
| + | </code> | ||
| + | Helper: | ||
| + | <code> | ||
| + | isNull(Void) = True | ||
| + | isNull(Cons(x, L)) = False | ||
| + | </code> | ||
| + | |||
| + | 3. | ||
| + | <code> | ||
| + | bool isNull(List l) { | ||
| + | return l == NULL; | ||
| + | } | ||
| + | |||
| + | int size(List l) { | ||
| + | if (isNull(l)) | ||
| + | return 0; | ||
| + | return 1 + size(l->next); | ||
| + | } | ||
| + | |||
| + | List add(List l, int x) { | ||
| + | if isNull(l)) | ||
| + | return Cons(x, Void()); | ||
| + | return Cons(l->e, add(l->next, x)); | ||
| + | } | ||
| + | |||
| + | List append(List l1, List l2) { | ||
| + | if (isNull(l1)) | ||
| + | return l2; | ||
| + | return Cons(l1->e, append(l1->next, l2)); | ||
| + | } | ||
| + | |||
| + | List reverse(List l) { | ||
| + | if (isNull(l)) | ||
| + | return Void(); | ||
| + | return append(reverse(l->next), Cons(l->e, Void())); | ||
| + | } | ||
| + | </code> | ||