Mai intai trebuie sa te autentifici.
Diferente pentru arbori-indexati-binar intre reviziile #1 si #2
Nu exista diferente intre titluri.
Diferente intre continut:
h2. Arbori indexaţi binar
h1. Arbori indexaţi binar
== include(page="template/implica-te/scrie-articole" user_id="Marius") == (Categoria _Structuri de date_, Autor _Mihai Scorţaru_) (toc){width: 25em}*{text-align:center} *Conţinut:*
* 'Titlu':arbori-indexati-binar
* 'Introducere':arbori-indexati-binar#introducere Problema determinării sumei elementelor unei subsecvenţe a unui şir ale cărui valori se modifică în timp real apare destul de des în diferite aplicaţii. Ea a apărut, sub diverse forme şi la anumite concursuri de programare. În cadrul acestui articol vom prezenta o structură de date care poate fi folosită pentru rezolvarea eficientă a acestei probleme. h2(#introducere). Introducere Prin _subsecvenţă_ înţelegem un subşir ale cărui elemente se află pe poziţii consecutive în şirul iniţial. De exemplu, $(2, 3, 4)$ este o subsecvenţă a şirului $(1, 2, 3, 4, 5)$ formată din al doilea, al treilea şi al patrulea element al şirului, în timp ce $(1, 2, 4)$ nu este o subsecvenţă deoarece nu este formată din elemente aflate pe poziţii consecutive. În cadrul acestui articol vom identifica o subsecvenţă prin extremităţile sale (poziţia cea mai din stânga şi poziţia cea mai din dreapta din şir). O subsecvenţă care începe în poziţia $a$ şi se termină în poziţia $b$ va fi notată cu $<a, b>$. Pentru şirul $(1, 2, 3, 4, 5)$ subsecvenţa $(2, 3, 4)$ va fi notată prin $<2, 4>$ dacă numerotarea elementelor începe cu $1$ sau prin $<1, 3>$ dacă numerotarea începe de la $0$. Deseori, avem nevoie de informaţii referitoare la subsecvenţele unui şir cum ar fi suma elementelor, produsul lor, valoarea minimă, valoarea maximă etc. La prima vedere, rezolvarea acestei probleme pare destul de simplă (de exemplu, pentru sumă se parcurg elementele subsecvenţei şi se adună). Totuşi, acest algoritm este ineficient datorită faptului că necesită parcurgerea întregii subsecvenţe. Vom arăta că există algoritmi pentru care o astfel de parcurgere nu este necesară. Totuşi, dacă am efectua o singură dată sau de un număr limitat de ori o astfel de parcurgere, algoritmul ar putea părea performant, viteza de execuţie fiind relativ mare. Problema se complică dacă elementele şirului se modifică în timp real. h3. Modificări în timp real Să presupunem că există două tipuri de operaţii care pot fi efectuate asupra unui şir. Primul tip constă în modificarea valorii unui element, în timp ce al doilea reprezintă interogări (cereri de informaţii) referitoare la anumite subsecvenţe ale şirului. De obicei, cele două tipuri de operaţii sunt "amestecate" în sensul că nu vor fi doar modificări urmate din interogări, ci putem avea o modificare, urmată de două interogări, urmate de cinci modificări, urmate de alte două interogări etc. Aşadar, putem spune că elementele şirului se modifică în timp real şi interogările se referă la starea curentă a şirului (cea din momentul cererii de informaţii). h3. Enunţul problemei În cele ce urmează vom prezenta un enunţ al problemei, particularizat pentru cazul în care interogările se referă la suma elementelor subsecvenţelor. bq. Se consideră un şir de numere întregi care are toate elementele nule. O modificare a unui element constă în adunarea unei valori la valoarea curentă (pot fi realizate şi scăderi care au forma adunării unor valori negative). Pe parcursul modificărilor pot apărea interogări referitoare la suma elementelor unei subsecvenţe a şirului. Problema poate fi enunţată în multe alte forme. Una dintre ele ar putea fi următoarea... bq. Un furnizor lucrează cu $N$ distribuitori; în fiecare moment distribuitorii pot efectua plăţi sau pot cumpăra produse. De asemenea, în fiecare moment furnizorul poate cere informaţii referitoare la suma totală a datoriilor pe care le au magazinele cu numere de ordine cuprinse între două valori date. (?) Evident, există multe alte enunţuri echivalente. De asemenea, pot apărea enunţuri în care operaţia de însumare ar putea fi înlocuită cu altele. De exemplu, furnizorul ar putea dori să cunoască datoria maximă a unui magazin care are numărul de ordine cuprins între două valori date. h3. Exemplu Vom exemplifica acum evoluţia în timp real a unui şir format din cinci elemente, prezentând valorile şirului după fiecare modificare şi rezultatul fiecărei interogări. Operaţia _Iniţializare_ constã în setarea la $0$ a valorilor tuturor elementelor. Operaţia _Adună(i, x)_ constă în adunarea valorii $x$ la valoarea curentă a celui de al $i$-lea element. Operaţia _Sumă(a, b)_ furnizează suma elementelor subsecvenţei $<a, b>$. table{width: 200px; text-align: center}. | _Operaţie_ | _Şir / Rezultat_ | | Iniţializare | 0 0 0 0 0 | | Adună(1, 3) | 3 0 0 0 0 | | Adună(4, 5) | 3 0 0 5 0 | | Sumă(4, 4) | 5 | | Adună(4, 2) | 3 0 0 7 0 | | Adună(2, 3) | 3 3 0 7 0 | | Sumă(2, 5) | 10 | | Sumă(2, 4) | 10 | | Adună(5, 2) | 3 3 0 7 2 | | Sumă(2, 4) | 10 | | Sumă(2, 5) | 12 | | ... | ... | h2. Cazul unidimensional Din modul în care a fost enunţată problema, rezultă că operaţiile efectuate asupra unui tablou unidimensional; aşadar, acesta este cazul unidimensional al problemei. Vom prezenta în continuare trei algoritmi care pot fi folosiţi pentru rezolvarea problemei şi apoi le vom studia performanţele. h3. Algoritmul naiv Cea mai intuitivă metodă de rezolvare constă în păstrarea unui vector cu valorile şirului, modificarea lor atunci când este necesar şi calcularea sumelor în momentul în care apar interogări. Pentru a prezenta algoritmul vom considera că o modificare este codificată prin valoarea $1$, iar o interogare prin valoarea $2$. Ar fi necesară o a treia operaţie (codificată prin $3$) car ar indica faptul că nu mai există modificări sau interogări, deci execuţia poate fi încheiată. Versiunea în pseudocod este prezentată în continuare: == code(cpp) | // iniţializări scrie „Introduceţi numărul de elemente:” citeşte N // dimensiunea şirului pentru i = 1, N execută a[i] = 0 // valorile iniţiale sunt nule sfârşit pentru scrie „Introduceţi codul operaţiei:” citeşte cod cât timp cod <> 3 execută dacă cod = 1 atunci // modificare scrie „Introduceţi indicele elementului care va fi modificat:” citeşte ind scrie „Introduceţi valoarea care va fi adunată (valoare negativă pentru scăderi):” citeşte val a[ind] = a[ind] + val altfel // interogare scrie „Introduceţi extremităţile subsecvenţei:” citeşte st, dr sumă = 0 pentru i = st, dr execută sumă = sumă + a[i] sfârşit pentru scrie „Suma elementelor subsecvenţei este: ”, sumă sfârşit dacă scrie „Introduceţi codul operaţiei:” citeşte cod sfârşit cât timp == Se observă că modificările se efectuează în timp constant deoarece implică doar accesarea unui element al vectorului şi modificarea valorii sale. Datorită faptului că pentru calcularea sumei elementelor unei subsecvenţe este necesară parcurgerea tuturor elementelor subsecvenţei, această operaţie are ordinul de complexitate $O(L)$, unde $L$ este lungimea subsecvenţei. Trebuie observat faptul că algoritmul este acelaşi dacă operaţia de însumare este înlocuită cu o alta (calcularea produsului, stabilirea minimului etc.). h3. Vector de sume