Differences

This shows you the differences between two versions of the page.

Link to this comparison view

sda-ab:laboratoare:06 [2021/02/25 17:23]
smaranda.bogoi
sda-ab:laboratoare:06 [2021/03/22 05:39] (current)
gabriel.rusu [1. Obiectivele laboratorului]
Line 9: Line 9:
   *Realizarea diferitelor operații folosint arborii binari de căutare   *Realizarea diferitelor operații folosint arborii binari de căutare
  
-Structura laboratorului se gaseste in **[[http://gooogle.com|acest link.]]**+Structura laboratorului se gaseste in **[[https://github.com/​sda-ab/​lab-05-tasks|acest link.]]**
  
 ====== Introducere ====== ====== Introducere ======
Line 84: Line 84:
 {{ :​sda-ab:​laboratoare:​arborebinar.png?​400 |}} {{ :​sda-ab:​laboratoare:​arborebinar.png?​400 |}}
  
-====== 2.2 Caracterizarea unui algoritm ======+**Alte notiuni introductive**
  
 +**Arbore binar plin**
  
-====== Algoritmi de căutare ====== +Un arbore binar este plin dacă nu există niciun nod intern la care mai putem lega un nod-copil nou(Toate nodurileîn afară ​de frunze, au număr maxim de copii).
-  * implica gasirea unui element cu o anumita proprietate intr-o colectie cu elemente de acel tip  +
-  * elementele pot sa fie inregistrari intr-o baza de date, elemente intr-un vector, text in fisiere, noduri intr-un arboremuchii sau noduri intr-un graf sau elemente in alte spatii ​de cautare +
-  * sunt algoritmi ​de baza, foarte utilizati ​+
  
-**Tipuri de cautari** +**Arbore binar complet**
-  * Cautare liniara intr-o multime neordonata ( Unordered Linear Search) +
-  * Cautare liniara intr-o multime ordonata ( Sorted/​Ordered Linear Search) +
-  * Cautare binara ( Binary search) +
-  * Tabele de dispersie +
-  * Cautare specializata pentru siruri de caractere (tries, arbori de sufixe, etc)+
  
-**Cautare liniara/​secventiala ​ intr-o multime neordonata**+Un arbore binar este complet dacă fiecare nivel(**cu posibila excepţie a ultimului**) este complet ocupat.
  
-Se presupune dat un vector neordonat. Este necesara parcurgerea intregului vector pentru a verifica unde se gaseste elementul.+**Arbore binar perfect**
  
-<​code>​ +Un arbore binar este perfect dacă este complet ocupat pe fiecare nivel(fără excepţii).
-int search(int v[], int n, int data +
-{ int i;  +
-  for (i=0; i<n; i++)  +
-  if (v[i] == data) return i;  +
-  return -1;  +
-}  +
-</​code>​+
  
 +<note important>​Puteţi întâlni **variante diferite** pentru ultimele trei definiţii şi, de aceea, pot apărea confuzii legate de semnificaţia termenilor **plin, complet şi perfect**. În cazul în care aveţi de lucrat cu arbori binari plini/​compleţi/​perfecţi,​ asiguraţi-vă că toată lumea se referă la aceleaşi noţiuni.</​note>​
  
-<​note>​cazul cel mai nefavorabil - algoritmul examineaza n numere pentru cautare (fara succes);  +=== 2.2  Reprezentare ===
-cazul mediu - sunt evaluate aproximativ n/numere pentru cautarea cu succes; +
-Complexitatea din punct de vedere al duratei este O(n); +
-Complexitatea din punct de vedere al memoriei este O(1) – nu mai trebuie alte resurse fata de datele initiale </​note>​+
  
 +Structura nodului unui arbore este urmatarea:
 +<​code>​ struct node {
 +     int data;
 +     ​struct node* left;
 +     ​struct node* right;
 +};</​code>​
  
-**Cautare binara** +=== 2.3 Parcurgere === 
-Se considera vectorul sortat. Cautarea se face impartind, la fiecare pas, domeniul de cautare in doua parti si se selecteaza cel care contine elementul de interes ​+  ​*În adâncime 
 +    ​*Preordine (RSD) 
 +       *Se parcurge rădăcina 
 +       *Se parcurge subarborele stâng 
 +       *Se parcurge subarborele drept 
 +    *<code c>void search_tree_preordine (tree *root) { 
 +     if( root!=NULL){ 
 +          cout << root->​data <<"​\n";​ 
 +          search_tree_preordine(root->​left);​ 
 +          search_tree_preordine(root->​right);​ 
 +     } 
 +}</​code>​ 
 +   ​*Inordine (SRD) 
 +       *Se parcurge subarborele stâng 
 +       *Se parcurge rădăcina 
 +       *Se parcurge subarborele drept 
 +        
 +    *<code c>void search_tree_inordine (tree *root) { 
 +     if( root!=NULL){ 
 +          search_tree_preordine(root->​left);​ 
 +          cout << root->​data <<"​\n";​ 
 +          search_tree_preordine(root->​right);​ 
 +     } 
 +}</​code>​
  
-<​code>​ 
-nt search_bin(int v[], int n, int data)  
-{int r=n-1, l=0;  
-while (r >= l) {  
- int m = (l+r)/​2; ​ 
- if (v[m]==data) return m;  
- if (v[m]>​data) r=m-1; ​ 
- else l=m+1; ​ 
- 
-return -1;  
- 
-</​code>​ 
  
- +  *Postordine ​(SDR
-<​note>​Cel mai nefavorabil caz - nu se examineaza mai mult de logn+1 numere acest lucru duce catre o complexitate de O(logN+       *Se parcurge subarborele stâng 
-Complexitatea spatiala este O(1) +       ​*Se parcurge subarborele ​drept 
-</​note>​ +       ​*Se parcurge rădăcina 
- +        
- +    ​*<code c>void search_tree_postordine ​(tree *root{ 
-====== 3. Algoritmi de sortare ====== +     ifroot!=NULL){ 
-Numim **sortare** orice aşezare a unor elemente date în aşa fel încât, după aşezare, să existe o ordine completă în funcţie de un atribut(numit cheie) al elementelor. +          ​search_tree_preordine(root->​left); 
- +          ​search_tree_preordine(root->right); 
-Pentru a exista o ordine completă, trebuie să alegem o relaţie pe care vrem sa o impunem. Dacă relaţia este valabilă între oricare două elemente pentru care primul element este aşezat la stânga celui de-al doilea, atunci avem o ordine completă. +          cout << root->data <<"​\n";​ 
- +     } 
-Exemplu: dacă alegem ​drept cheie un atribut număr întreg şi relaţia mai mic sau egal(⇐), obţinem ordinea crescătoare. +}</​code>​ 
- +  *În lățime 
-Vom descrie un algoritm de sortare prin: +   ​ 
- +     Această parcurgere reprezintă vizitarea „nivel ​cu nivel“ a arborelui.De exempluvom obține j,f,k,a,h,z,d pentru arborele: 
-  ​timp mediu - timpul de execuţie la care ne aşteptăm, în medie, pentru sortare +<​code ​c
-  * timp la limită- timpul de execuţie pentru cel mai rău caz posibil +   tree 
-  memorie - memoria maximă de care are nevoie algoritmul pentru sortare(excludem memoria deja alocată înainte de algoritm → vectorul efectiv ce va fi sortat+   --- 
-  * stabilitate - un algoritm stabil păstrează ordinea în care apar două elemente cu aceeaşi cheie(atributul după care sortăm+    ​j       <​--level ​
- +   ​\ 
-Folosim notaţia O(npentru a indica: +  ​f ​  ​k ​    <--level ​
- + / ​\   ​\ ​   
-  * un număr de operaţii de ordinul lui n. În acest caz, spunem că avem „complexitate de timp de ordinul lui n“ +  h   ​z ​  <--level 2 
-  * o dimensiune de ordinul lui n pentru memoria alocată. În acest caz, spunem că avem „complexitate de spaţiu de ordinul lui n“ + \ 
- +  ​d ​        ​<--level 3 
-Fiecare algoritm se bazează pe o metodă de sortare: +
- +
-  * Bubble sort interschimbare +
-  * Selection sort selecţie +
-  * Insertion sort - inserare +
-  * Merge sort - interclasare +
-  * Quick sort - partiţionare +
- +
- +
-**3.1 Bubble sort** +
-  * timp mediu: O(N^2) +
-  * timp la limită: O(N^2) +
-  * memorie: O(1) +
-  * Stabil: DA +
- +
-**Descriere** : +
-Sortarea prin metoda bulelor se consideră drept una din cele mai puţin efective metode de sortare, dar cu un algoritm mai simplu. +
- +
-Ideea de bază a sortării prin metoda bulelor este în a parcurge tabloulde la stânga spre dreaptafiind comparate elementele alăturate ​a[i] si a[i+1]. Dacă vor fi găsite 2 elemente neordonatevalorile lor vor fi interschimbate. +
-Parcurgerea tabloului de la stânga spre dreapta se va repeta atât timp cât vor fi întâlnite elemente neordonate. +
- +
-**Implementare** +
- +
-<code > +
-//sortare descrescatoare +
-void bubble(int a[],int n) +
-{ +
-    ​int i,​schimbat,​aux;​ +
-    do { +
-        schimbat = 0; +
-        // parcurgem vectorul +
-        for(i = 0; i n-1; i++) { +
-     ​// daca valoarea i din vectorul a este mai mica decat cea de pe pozitia i+1 +
-            if (a[i] a[i+1]) {  +
-                // interschimbare +
-         ​aux = a[i]; +
- a[i] = a[i+1]; +
- a[i+1] = aux; +
- schimbat = 1; +
-     } +
-        } +
-    } while(schimbat);​ +
-}+
 </​code>​ </​code>​
  
 +Vom folosi acest tip de parcurgere pentru a evidenția:
 +     ​*ierarhia posturilor unei companii,
 +     *un arbore genealogic,
 +     ​*arborele unui joc (unde rădăcina reprezintă starea curentă,​nivelul 1 posibilele mele mutări,​nivelul 2 posibilele mutări ale adversarului,​nivelul 3 posibilele mele mutari și tot așa).
  
-**3.2 Selection sort** +//Cum se realizează această implementare?//​ 
-  * timp mediu: O(N^2) +   ​ 
-  * timp la limită: O(N^2) +Vom folosi o coadă în care vom introduce rădăcinaapoi informația din stângaapoi informația ​din dreapta, apoi coborând pe subarborele stâng procedăm ​la fel, iar după ne vom întoarce pe subarborele drept să aplicăm aceeașoperație și tot așa până ​vom ajunge ​la frunze. 
-  * memorie: O(1) +Coada ne dă posibilitatea să scoatem prima informație,​prima băgată ⇒ierarhia
-  * Stabil: DA +<note tip>**Observatie!** Nodurile frunză nu au descendenți:nodul stâng șnodul drept pointează la NULL șnu trebuie adăugate în coadă.</note
- +=====3. Arbori binari de căutare  ====== 
-**Descriere :** +Un arbore binar de căutare este un arbore binar care are în plus următoarele proprietăți: 
-Acest algoritm selectează, la fiecare pas icel mai mic element ​din vectorul nesortat(de ​la poziţia ​i până la n)Valoarea minimă găsită la pasul i este pusă în vector la poziţia i, facându-se intereschimbarea cu poziţia actuală a minimului. Nu este un algoritm indicat pentru vectorii mari, în majoritatea cazurilor oferind rezultate mai slabe decât insertion sort şi bubble sort+  ​*Cheile stocate în noduri (informația utilă) aparțin unei mulțimi peste care există o relație de ordine
- +  *Cheia dintr-un nod oarecare este **mai mare** decât cheile tuturor nodurilor din subarborele stâng si este mai mică decât cheile tuturor nodurilor ce compun subarborele drept
-**Implementare** +Astfel,**valoarea maximă** dintr-un arbore binar de căutare se află în nodul din extremitatea dreaptă și se determină prin coborârea pe subarborele drept,iar **valoarea minimă** se află în nodul din extremitatea stângă. 
- +<note tip>**Observatie!** Parcurgerea //​inordine//​ produce o **secvență ordonată crescător** a cheilor ​din nodurile arborelui.</​note>​ 
-<​code>​ +=== 3.2 Operații ​===
-void selectionSort(int a[],int n) +
-+
- int i,​j,​aux,​min,​minPoz;​ +
- for(= 0; i < n - 1;i++) +
-+
- minPoz = i; +
- min = a[i]; +
- for(j = i + 1;j < n;​j++) ​//selectam minimul +
- //din vectorul ramas( de la i+1 la n) +
-+
- if(min ​a[j]) //sortare crescatoare +
- { +
- minPoz ​j; //pozitia elementului minim +
- min ​a[j]; +
-+
-+
- aux a[i] ; +
- a[i] ​a[minPoz]; //​interschimbare +
- a[minPoz] ​aux; +
-+
-+
-</​code>​ +
- +
- +
-**3.3 Insertion sort** +
-  * timp mediu: O(N^2) +
-  * timp la limită: O(N^2) +
-  * memorie: O(1) +
-  * Stabil: DA +
- +
-Descriere : +
-Spre deosebire ​de alţi algoritmi de sortare, sortarea prin inserţie este folosită destul de des pentru sortarea tablourilor cu număr mic de elemente. +
- +
-Sortarea prin inserţie seamană oarecum cu sortarea prin selecţie. Tabloul ​este împărţit imaginar ​în două pă- o parte sortată şi o parte nesortată. La început, partea sortată conţine primul element al tabloului şi partea nesortată conţine restul tabloului. +
-La fiecare pas, algoritmul ​ia primul element din partea nesortată şi il inserează în locul potrivit al părţii sortate+
-Când partea nesortată nu mai are niciun element, algoritmul se opreste. +
- +
-**Implementare** +
- +
-<​code>​ +
-void insertionSort(int a[], int n) +
-+
-    int i, j, aux; +
-    for (i = 1; i < n; i++) +
-    { +
-        j = i; +
-        while (j > 0 && a[j - 1] > a[j]) +
-        { //cautam pozitia pe care sa mutam a[i] +
-            aux = a[j]; //​interschimbare +
-            a[j] = a[j - 1]; +
-            a[--j] = aux; +
-        } +
-    } +
-+
-</​code>​ +
- +
-**3.4 Merge sort** +
-  timp mediu: O(N log N) +
-  ​timp la limită: O(N log N) +
-  ​memorie: O(N) +
-  ​Stabil: DA +
- +
- +
-**Descriere :** +
-În cazul sortării prin interclasare,​ vectorii care se interclasează sunt două secvenţe ordonate din acelaşi vector. Sortarea prin interclasare utilizează metoda Divide et Impera: se împarte vectorul ​în secvenţe ​din ce în ce mai mici, astfel încât fiecare secvenţă să fie ordonată la un moment dat şinterclasată cu o altă secvenţă din vector corespunzătoare. Practic, interclasarea va începe când se ajunge la o secvenţă formată din două elemente. Aceastaodată ordonată, ​se va interclasa cu o alta corespunzătoare(cu 2 elemente). Cele două secvenţe vor alcătui un subşir ordonat ​din vector mai mare(cu 4 elemente) care, la rândul lui, se va interclasa cu un subşir corespunzător(cu 4 elemente) ş.a.m.d+
- +
- +
-Subvectorii sortaţi sunt interclasaţi succesiv, ı̂n ordinea inversă divizarii, obţinând ı̂n final vectorul sortat. +
-Iată un exemplu pentru vectorul [38, 27, 43, 3, 9, 82, 10]: +
- +
-{{ :​sda-ab:​laboratoare:​screenshot_from_2021-01-12_21-59-59.png?​450 |}} +
- +
-**3.5 Quick sort** +
-  ​timp mediu: O(N log N) +
-  ​timp la limită: O(N^2) +
-  * memorie: O(log N) +
-  * Stabil: NU +
- +
-**Descriere :** +
-Quick Sort este unul dintre cei mai rapizi şi mai utilizaţi algoritmi de sortare până în acest moment, bazându-se pe tehnica „Divide et impera“. Deşi cazul cel mai nefavorabil este O(N^2), în practică, QuickSort oferă rezultate mai bune decât restul algoritmilor de sortare din clasa „O(N log N)“. +
- +
-Algoritmul se bazează pe următorii paşi: +
- +
-  ​alegerea unui element pe post de pivot +
-  ​parcurgerea vectorului ​din două părţi(de la stânga la pivot, de la dreapta la pivot, ambele în acelaşi timp) +
-  * interschimbarea elementelor care se află pe „partea greşită“ a pivotului(mutăm la dreapta pivotului elementele mai mari, la stânga pivotului elementel mai mici) +
-  * divizarea algoritmului:​ după ce mutăm elementele pe „partea corectă“ a pivotului, avem 2 subşiruri de sortat, iar pivotul se află pe poziţia bună. +
- +
- +
-====== 4Exercitii ​====== +
-1. Alegeţi un algoritm A(dintre Bubble, Insertion şi Selection) şi un algoritm B(dintre Merge şi Quick). Introduceţi variabile globale cu care să contorizaţi numărul de comparaţii pentru algoritmii A şi B. Comparaţi rezultatele pentru un vector de întregi de lungime n = 20. +
- +
-2. Implementaţi un algoritm(dintre Bubble, Insertion şi Selection) pentru sortarea unui vector cu n cuvinte de maxim 4 litere fiecare.+
  
-3. Implementaţi ​un algoritm(dintre Merge şi Quick) pentru sortarea unui vector ​de structuri, unde fiecare structură reprezintă un moment de timp(int ora,min,sec).+  ***Căutarea** unei chei într-un arbore binar de căutare este asemănătoare căutării binare:​cheia căutată este comparată cu cheia din nodul curent ​(inițial nodul rădăcină).În funcție de rezultatul comparației apar trei cazuri: 
 +    *acestea coincid ⇒ elementul a fost găsit 
 +    *elementul căutat este mai mic decât cheia din nodul curent ⇒ căutarea continuă în subarborele stâng 
 +    *elementul căutat este mai mare decât cheia din nodul curent ⇒ căutarea continuă in subarborele drept
  
 +  ***Înserarea** unui nod se face,în funcție de rezultatul comparației cheilor,în subarborele stâng sau drept.Dacă arborele este vid,se creează un nod care devine nodul rădăcină al arborelui.În caz contrar,​cheia se inserează ca fiu stâng sau fiu drept al unui nod din arbore.
  
-4. Considerăun pachet ​de cărţi. Extragem random n căi. Sortaţi aceste ​folosind metoda inserţiei.+  ***Ștergerea** unui nod este o operație puțin mai complicată,întrucât presupune o rearanjare a nodurilor.Pentru eliminarea unui nod dintr-un arbore binar de căutare sunt posibile următoarele cazuri: 
 +    *nodul de șters nu există ⇒ operația se consideră încheiată 
 +    *nodul de șters nu are succesori ⇒ este o frunză 
 +    *nodul de șters are un singur succesor ⇒ nodul se va șterge șse refac legăturile în arbore 
 +    *nodul de șters are doi succesori ⇒ se parcurge arborele drept,utându-se cea mai mică valoare,mai mare decât a nodului care trebuie șters șse refac legăturile cu acesta.
  
-5. Scrieţi ​un program eficient ​care să afişeze primele k cele mai mari elemente dintr-un vector. ​Elementele nu +====== 4.Exercitii propuse ====== 
-sunt ordonate, ci ordinea lor este una aleatoareDe exemplu ​dat vectorul v [1, 23, 12, 9, 30, 2, 50], dacă k 3, vrem cele mai mari 3 elemente care sunt +  -Se dă un vector cu n întregi. Scrieţi ​o funcţie ​care să creeze ​un arbore binar de căutare cu valorile din vector. 
-50, 30, 23+  -Se dă un arbore binar ce stochează întregi. Scrieţi o funcţie care verifică dacă arborele ​este binar de căutare. 
 +  -Se dă un arbore binar de căutare ce stochează întregi. Scrieţi o funcţie care verifică dacă o valoare ​dată se află în arbore(căutare). 
 +  -Acelaşi arbore – inserare(şi să rămână arbore de căutare) 
 +  -Acelaşi arbore – ştergere(şi să rămână arbore de căutare) 
 +=== 4.1. Intrebari de interviu ===
  
 +  -Se dă V(un vector de n întregi) şi P(un vector de taţi de lungime n). Verificaţi dacă se poate construi un arbore binar de căutare cu valorile din V şi legăturile copil-părinte din P.
 +  -Fie un arbore binar perfect cu înălţimea H. Creaţi (H + 1) vectori/​liste,​ câte unul/una pentru fiecare nivel din arbore. Afişaţi fiecare nivel(parcurgerea în lăţime) cu ajutorul vectorilor/​listelor.
 +  -Găsiţi cel mai apropiat strămoş comun pentru două noduri dintr-un arbore binar.
 +  -Se dau doi arbori binari cu întregi, A1 şi A2, iar A1 conţine mult mai multe noduri decât A2. Verificaţi dacă A2 arată la fel ca un subarbore din A1.(“Arată la fel”, adică valorile întregi sunt aceleaşi)
sda-ab/laboratoare/06.1614266585.txt.gz · Last modified: 2021/02/25 17:23 by smaranda.bogoi
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0