Differences

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

Link to this comparison view

sd-ca:laboratoare:lab-08 [2022/04/27 18:19]
radu_stefan.minea [Exerciții]
sd-ca:laboratoare:lab-08 [2025/05/19 18:03] (current)
roberto_giulio.pal [Exerciții]
Line 1: Line 1:
-====== Laborator ​Arbori Binari ​======+====== Laborator ​11 Grafuri - Advanced  ​======
  
 Responsabili Responsabili
-  * [[mailto:​mitapirvuet@gmail.com|Mihai Pirvulet]] +  * [[stef.dascalu@gmail.com|Ștefan-Teodor Dascălu]] 
-  * [[mailto:​radustefanminea@gmail.com|Radu Minea]]+  * [[melih.riza03@gmail.com|Melih Riza]]
  
 ===== Obiective ===== ===== Obiective =====
  
-În urma parcurgerii ​articolului, studentul va fi capabil să: +În urma parcurgerii ​acestui laborator, studentul va fi capabil să: 
-  * înţeleagă noţiunea ​de arbore şi structura unui arbore binar +  * găsească soluțiile unor probleme folosind algoritmii ​de parcurgere 
-  * construiască, în limbajul C, un arbore binar +  * să folosească şi să adapteze algoritmii ​de parcurgere pentru implementarea soluţiilor găsite
-  * realizeze o parcurgere a structurii ​de date prin mai multe moduri +
-===== Noțiuni teoretice =====+
  
-==== Noțiunea de arbore. Arbori binari ​==== +===== Importanţă =====
-Matematic, un arbore este un graf neorientat conex aciclic.+
  
-În ştiinţa calculatoarelor,​ termenul de **arbore** este folosit ​pentru a desemna o structură de date care respectă definiţia de mai sus, însă are asociate un nod rădăcină şo orientare înspre sau opusă rădăcinii.+Grafurile sunt utile pentru a modela diverse probleme şi se regăsesc implementaţi în multiple aplicaţii practice:
  
-Arborii sunt folosiţi în general pentru a modela o **ierarhie de elemente**.+  * reţele de calculatoare (ex: stabilirea unei topologii fără bucle) 
 +  ​pagini Web (ex: Google PageRank) 
 +  ​rețele sociale (ex: calcul centralitate) 
 +  ​hărţi cu drumuri (ex: drum minim) 
 +  ​modelare grafică (ex: prefuse, graph-cut)
  
-Astfel, fiecare element (**nod**) poate deţine un număr de unul sau mai mulţi descendenţi,​ iar în acest caz nodul este numit **părinte** al nodurilor descendente (**copii** sau **fii**).+===== Aplicaţii parcurgeri =====
  
-Fiecare nod poate avea un **singur nod părinte**. +==== Componente conexe ====
-Un nod fără descendenţi este un **nod terminal**, sau **nod frunză**.+
  
-În schimb, există un singur nod fără părinteiar acesta este întotdeauna **rădăcina arborelui** ​(**root**).+Se numeşte componentă conexă a unui graf neorientat ''​G = (VE)''​ un subgraf ''​G1 = (V1, E1)''​ în care pentru orice pereche de noduri ''​(A,​ B)''​ din V1 există un lanţ de la ''​A''​ la ''​B'',​ implicit şi de la ''​B''​ la ''​A''​.
  
-Un **arbore binar** este un caz special de arboreîn care fiecare nod poate avea maxim **doi descendenţi**: +**Observaţie** Nu există ​un alt subgraf al lui ''​G''​''​G2 = (V2, E2)'' ​care să îndeplinească această condiţie şcare să îl conţină pe ''​G1''​. În acest caz, ''​G2''​ va fi componenta conexă, iar ''​G1''​ nu.
-  *nodul stâng +
-  *nodul drept.+
  
-În funcţie de elementele ce pot fi reprezentate în noduri şi de restricţiile aplicate arborelui, se pot crea structuri de date cu proprietăţi deosebite: heap-uri, arbori AVL, arbori roşu-negru,​ arbori Splay şi multe altele. O parte din aceste structuri vor fi studiate la curs şi în laboratoarele viitoare.+=== Algoritm ===
  
-În acest articol ne vom concentra asupra unei utilizări comune a arborilor binari, şi anume pentru a reprezenta şi evalua expresii logice+  * Atât o parcurgere ''​BFS''​cât şi una ''​DFS'',​ pornind dintr-un nod A, va determina componenta conexa din care face parte ''​A''​
-==== Reprezentarea arborilor binari ====+  * Pentru a determina toate componentele conexe ale unui graf ''​G ​(V, E)'',​ se vor parcurge nodurile din ''​V''​. 
 +  * Din fiecare nod care nu face parte dintr-o componentă conexă găsită anterior, se va porni o parcurgere ''​BFS''​ sau ''​DFS''​.
  
-Arborii binari pot fi reprezentați în mai multe moduri. Structura din spatele acestora poate fi un simplu vector, alocat dinamic sau nu, sau o structură ce folosește pointeri, așa cum îi vom reprezenta în acest articol.+=== Pseudocod ===
  
-<​code ​c binary_tree.h+<​code>​ 
-typedef struct b_node_t b_node_t; +// Inițializări 
-struct b_node_t ​+pentru fiecare nod u din V 
-    ​/* left child */ +
-    ​b_node_t *left; +    ​stare[u] = nevizitat 
-    /* right child */ +} 
-    b_node_t *right;+componente_conexe = 0
  
-    ​/* data contained by the node *+// Funcţie de vizitare a nodului 
-    ​void *data; +vizitare(nod) 
-};+
 +    stare[nod] = vizitat 
 +    ​printeaza nod 
 +}
  
-typedef struct b_tree_t b_tree_t; +// Parcurgerea în adâncime 
-struct b_tree_t ​+DFS(nod) 
-    ​/* root of the tree */ +
-    ​b_node_t *root;+    ​stiva s 
 +      
 +    viziteaza nod  
 +    ​s.introdu(nod)
     ​     ​
-    /* size of the data contained by the nodes *+    ​cât timp stiva s nu este goală 
-    ​size_t data_size; +    { 
-};+        nodTop = nodul din vârful stivei  
 +                
 +        vecin = află primul vecin nevizitat al lui nodTop. 
 +        dacă vecin există 
 +        { 
 +            viziteaza v 
 +            s.introdu(v) 
 +        }   
 +        altfel 
 +        { 
 +            s.scoate(nodTop) 
 +        } 
 +    } 
 +
 + 
 +// Parcurgerea nodurilor din V 
 +pentru fiecare nod u din V 
 +{ 
 +    ​dacă stare[u] == nevizitat 
 +    { 
 +        componente_componente = componente_conexe + 1 
 +        DFS(u) 
 +    } 
 +}
 </​code>​ </​code>​
  
-Structura nodului de mai sus este clară: +=== Exemplu ===
-*pointer către fiul stâng +
-*pointer către fiul drept +
-*pointer către date+
  
-Pentru a ne reaminti cum alocăm/​dealocăm memorie: +Graful din imagine are 4 componente conexe.
-<code c> +
-/** +
- * Creates a new binary tree +
- * @data_size: size of the data contained by the tree's nodes +
- * @return: pointer to the newly created tree +
- */ +
-b_tree_t *b_tree_create(size_t data_size);+
  
-/** +{{sd-ca:laboratoare:componenteConexe.png}} 
- * Clear the whole memory used by the tree and its nodes + 
- * @b_treethe binary tree to be freed +==== Aflarea distanţei minime între două noduri ==== 
- * @free_datafunction used to free the data contained by a node + 
- */ +Dacă toate muchiile au același cost, putem afla distanța minimă între două noduri ''​A''​ și ''​B''​ efectuând o parcurgere ''​BFS''​ din nodul ''​A''​ și oprindu-ne atunci când nodul ''​B''​ a fost descoperit. Reamintindu-ne că nivelul unui nod este analog distanței, în muchii, față de sursă, și că ''​BFS''​ descoperă un nod de pe nivelul ''​N''​ numai după ce toate nodurile de pe nivele inferioare au fost descoperite,​ este ușor de văzut că nivelul nodului ''​B''​ în parcurgere corespunde distanței minime între ''​A''​ și ''​B''​.
-void b_tree_free(b_tree_t *b_tree, void (*free_data)(void *)); +
-</​code>​+
  
-De exemplu, dacă dorim să creem un arbore binar ce conține elemente ​de tip *char*codul arată astfel: +Pentru a reține distanța și drumul exact de la ''​A''​ la ''​B''​se vor reține pentru fiecare nod ''​d[x]''​ (distanța de la ''​sursă''​ la ''​x''​) și ''​p[x]'' ​(părintele lui ''​x''​ în drumul de la sursă spre ''​x''​). În momentul descoperirii unui nod ''​y''​ al cărui părinte este ''​x'',​ se vor face următoarele atribuiri:
-<code c> +
-b_tree_t *char_tree = b_tree_create(sizeof(char));+
  
-b_tree_free(char_tree,​ free);+<​code>​ 
 +d[y] = d[x] + 1 
 +p[y] = x
 </​code>​ </​code>​
-==== Parcurgerea arborilor ==== 
  
-Se implementeaza foarte usor recursiv:+sursa având ''​d[A] = 0''​ și ''​p[A] = NULL''​.
  
-==== 1. Preordine ==== +Observații:​ 
-  *Se parcurge **dăcina** +  *dacă parcurgerea BFS se încheie fără ca nodul B să fi fost descoperit, nu există drum între A și B și deci distanța între acestea este infinită. 
-  *Se parcurge subarborele **stâng** +  *Algoritmul funcționează corect numai în situații de cost uniform (toate muchiile au același cost). Pentru grafuri cu muchii de costuri diferite, sunt necesari algoritmi mai avansați, cum ar fi: Dijkstra, Bellman-Ford sau Floyd-Warshall.
-  *Se parcurge subarborele **drept**+
  
-==== 2. Inordine ====+=== Pseudocod ​===
  
-  *Se parcurge subarborele **stâng** +<​code>​ 
-  *Se parcurge **rădăcina** +// Inițializări 
-  *Se parcurge subarborele **drept**+pentru fiecare nod u din V 
 +
 +    stare[u] = nevizitat 
 +    ​d[u] = infinit 
 +    p[u] = null 
 +}
  
-Exemplu: +// Distanța între sursă și destinație 
-<code c> +distanța(sursădestinație)
-static void __b_tree_print_inorder(b_node_t *b_nodevoid (*print_data)(void *))+
 { {
- if (!b_node) 
- return; 
  
- /* TODO *+    stare[sursă] = vizitat 
- __b_tree_print_inorder(b_node->​leftprint_data);+    d[sursă] = 0 
 +    enqueue(Q,​sursă) ​               ​// Punem nodul sursă în coada Q 
 +  
 +    // BFS 
 +    cât timp coada Q nu este vidă 
 +    { 
 +        v = dequeue(Q)              // Extragem nodul v din coadă 
 +        pentru fiecare u dintre vecinii lui v 
 +            dacă stare[u] == nevizitat 
 +            { 
 +                stare[u] = vizitat 
 +                p[u] = v 
 +                d[u] = d[v] + 1 
 +                enqueue(Q,u       // Adăugăm nodul u în coadă 
 +            } 
 +    } 
 +    return d[destinație] ​           // Dacă este infinit, nu există drum 
 +
 +</​code>​
  
- print_data(b_node->​data);​+==== Sortarea topologică ====
  
- __b_tree_print_inorder(b_node->rightprint_data);+Se dă un graf orientat aciclic. Orientarea muchiilor corespunde unei relații de ordine de la nodul sursă către cel destinație. O sortare topologică a unui astfel de graf este o ordonare liniară a vârfurilor sale astfel încât, dacă ''​(u,​v)''​ este una dintre muchiile grafului, ''​u''​ trebuie să apară înaintea lui ''​v''​ în înșiruire. Dacă graful ar fi ciclic, nu ar putea exista o astfel de înșiruire (nu se poate stabili o ordine între nodurile care alcătuiesc un ciclu). 
 + 
 +Sortarea topologică poate fi văzută și ca plasarea nodurilor de-a lungul unei linii orizontale astfel încât toate muchiile să fie direcționate de la stânga la dreapta (să nu existe nici o muchie înapoispre părinte)
 + 
 +=== Pseudocod === 
 + 
 +<​code>​ 
 +// Inițializări 
 +pentru fiecare nod u din V 
 +
 +    stare[u] = nevizitat 
 +    p[u] = NULL 
 +    tDesc[u] = 0 
 +    tFin[u] = 0
 } }
 +contor_timp = 0
  
-void b_tree_print_inorder(b_tree_t *b_tree, void (*print_data)(void *))+// Funcţie de vizitare a nodului 
 +vizitare(nod)
 { {
- __b_tree_print_inorder(b_tree->​root,​ print_data);​ +    contor_timp = contor_timp + 1 
- printf("​\n"​);​+    ​tDesc[nod] = contor_timp 
 +    stare[nod] = vizitat 
 +    printeaza nod
 } }
 +
 +// Parcurgere în adâncime
 +DFS(nod)
 +{
 +    stiva s
 +     
 +    viziteaza nod 
 +    s.introdu(nod)
 +    ​
 +    cât timp stiva s nu este goală
 +    {
 +        nodTop = nodul din vârful stivei ​
 +               
 +        vecin = află primul vecin nevizitat al lui nodTop.
 +        dacă vecin există
 +        {
 +            p[v] = nodTop
 +            viziteaza v
 +            s.introdu(v)
 +        }  ​
 +        altfel
 +        {
 +            contor_timp = contor_timp + 1
 +            tFin[nodTop] = contor_timp
 +            s.scoate(nodTop)  ​
 +        }
 +    }
 +}
 +
 +// Parcurgere noduri și calculare tDesc și tFin pentru fiecare nod
 +pentru fiecare nod u din V
 +{
 +    dacă u nu a fost vizitat
 +    {
 +         ​DFS(u)
 +    }
 +}
 +
 +// Sortare topologica
 +sortează nodurile din V descrescător în funcție de tFin[nod]
 </​code>​ </​code>​
-==== 3. Postordine ==== 
  
-  *Se parcurge subarborele **stâng** +=== Exemplu ===
-  *Se parcurge subarborele **drept** +
-  *Se parcurge **rădăcina**+
  
-==== 4Lățime ====+Profesorul Bumstead își sortează topologic hainele înainte de a se îmbrăca. 
 +  * fiecare muchie ''​(u,​ v''​) înseamna că obiectul de îmbrăcăminte ''​u''​ trebuie îmbrăcat înaintea obiectului de îmbrăcaminte ''​v''​. Timpii de descoperire ''​(tDesc)''​ și de finalizare ''​(tFin)''​ obținuți în urma parcurgerii DFS sunt notați lângă noduri. 
 +  * același graf, sortat topologic. Nodurile lui sunt aranjate de la stânga la dreapta în ordinea descrescătoare a ''​tFin''​. Observați că toate muchiile sunt orientate de la stânga la dreapta. Acum profesorul Bumstead se poate îmbrăca liniștit. ​
  
-Se folosește o coadă, iar la fiecare pas se extrage din această coadă câte un nod și se adăugă înapoi în coadă nodul stâng, respectiv drept al nodului scos. Acest algoritm continuă până când coada devine goală.+{{sd-ca:​laboratoare:​topologie.jpg}}
  
-<note important>​ +Așa cum se observă din imagine, sortarea topologică constă în sortarea nodurilor descrescător după timpii de finalizare. Demonstrația acestei afirmații se face simplu, arătând că nodul care se termină mai târziu trebuie să fie efectuat înaintea celorlalte noduri finalizate.
-Nodurile frunză nu au descendenţi -> nodul stâng şi nodul drept pointează la **NULL** şi nu trebuie adăugate în coadă. +
-</​note>​+
  
-==== Arbori asociați expresiilor ​====+==== Graf bipartit ​====
  
-O expresie matematică este un şir de caractere compus ​din+Se numește graf bipartit un graf ''​G = (V, E)''​ în care mulțimea nodurilor poate fi împărțită în două mulțimi disjuncte ''​A''​ și ''​B''​ astfel încât ''​V = A U B''​ şi ''​E ​este inclus în A x B''​ (orice muchie leagă ​un nod din ''​A''​ cu un nod din ''​B''​). Dacă un graf conține noduri izolate, acesta nu este bipartit.
-  *variabile +
-  *constante +
-  *operatori +
-  *paranteze (eventual).+
  
-Fiecărei expresii i se poate asocia un arbore binar, în care: +=== Algoritm ===
-  *nodurile interioare reprezintă **operatorii** +
-  *frunzele reprezintă **constantele** şi/sau **variabilele**.+
  
-În terminologia limbajelor formale şi compilatoareloracest arbore se mai numeşte ş**Abstract Syntax Tree (AST)**.+  * Pentru ​determina dacă un graf este bipartit sau nuuna din metode constă în efectuarea de parcurgeri ''​BFS''​ șatribuirea de etichete nodurilor conform cu paritatea nivelului acestora în parcurgere ​(''​A''​ pentru nodurile de pe nivel par, ''​B''​ pentru nodurile de pe nivel impar).  
 +  ​Atunci când se adaugă vecinii nevizitați ai unui nod în coadă, se vor verifica de asemenea etichetele vecinilor deja vizitați: dacă se descoperă că unul din aceștia are aceeași etichetă ca cea atribuită nodului curent, graful are o muchie între noduri de pe același nivel și deci nu poate fi bipartit.  
 +  ​În caz contrar (s-a realizat parcurgerea ''​BFS''​ fără a apărea această situație), graful este bipartit și nodurile sunt etichetate cu mulțimea din care fac parte.
  
-Pentru expresia **(a+1)*(b+10)+25/​c** , arborele asociat este prezentat mai jos: +=== Pseudocod ===
-{{ sd-ca:​laboratoare:​imagine-ast.png?​nolink&​600 |}}+
  
-<hidden+<code
-==== Evaluarea expresiilor ====+cât timp încă sunt noduri nevizitate 
 +
 +    n primul nod nevizitat. 
 +     
 +    dacă n este izolat  
 +    { 
 +        return false 
 +    } 
 +     
 +    nivel[n] ​par 
 +    enqueue(Q, n)  // Punem nodul sursă în coada Q
  
-Următorul pseudo-cod reprezintă în linii mari algoritmului de evaluare a expresiilor reprezentate sub formă de arbori binari: +    // BFS 
-  +    ​cât timp coada Q nu este vidă 
-<code c++> +    { 
-Evalueaza(Node nod) { +        ​v = dequeue(Q) ​          // Extragem nodul v din coadă 
-    ​// Daca nu este nod terminal... +        ​pentru fiecare u dintre vecinii lui v 
-    ​if (nod->​left || nod->​right) ​+        dacă nivel[u] nedefinit 
-        // Evaluam expresiile subarborilor... +        { 
-        ​res1 Evalueaza(nod->​left); +            nivel[u] ​= (nivel[v] == par? impar : par 
-        res2 = Evalueaza(nod->​right)+            ​enqueue(Q, u   // Adăugăm nodul u în coadă 
-         +        } 
-        ​// ... si combinam rezultatele aplicand operatorul +        ​altfel dacă nivel[u] == nivel[v] 
-        ​return AplicaOperator(nod->​op,​ res1, res2); +        { 
-   else { +            ​// Două noduri consecutive au acelaşi nivel 
-        ​// Daca nodul terminal contine o variabila, atunci intoarcem valoarea variabilei +            // Graful nu este bipartit 
-        ​if (nod->​var) ​+            return ​false
-            ​return Valoare(nod->​var);​ +
-        } else { // Avem o constanta +
-            return ​nod->​val;​+
         }         }
-   }+    ​}
 } }
 +
 +// S-a terminat parcurgerea BFS fără să apară două noduri consecutive pe acelaşi nivel
 +// Graful este bipartit
 +return true
 </​code>​ </​code>​
-</​hidden>​ 
-==== Cel mai mic strămoș comun ==== 
  
-O problemă importantă în analiza arborilor este determinarea celui mai mic strămoș comun (LCA - Lowest Common Ancestor). LCA-ul a două noduri, u si v, este nodul cel mai depărtat de rădăcină care îi are pe u și v ca descendenți.+=== Exemplu ===
  
-{{:sd-ca:​laboratoare:​diagram1-2.png?600|}}+{{sd-ca:​laboratoare:​bipartit.jpg}}
  
-Spre exemplu, cel mai mic strămoș comun al nodurilor 1 și 12 este 0, în timp ce pentru nodurile 4 și 7, acesta este 1.+==== Ciclu hamiltonian ====
  
 +Un lanţ hamiltonian într-un graf orientat sau neorientat ''​G = (V, E)'',​ este o cale ce trece prin fiecare nod din ''​V''​ o singură dată. Dacă nodul de început şi cel de sfârşit coincid (este vizitat de două ori) vom spune că lanţul formează un **ciclu hamiltonian**.
  
-===== Schelet =====+Un graf ce conţine un ciclu hamiltonian se numeşte graf hamiltonian.
  
 +=== Algoritm ===
  
-{{:sd-ca:​laboratoare:​lab_8:​lab08_trees.zip|}}+În cadrul acestui laborator, vom folosi metoda backtracking pentru găsirea unui ciclu hamiltonian. Pentru contruirea soluţiei, se menţine o listă în care sunt adăugate nodurile parcurse:
  
 +  * La fiecare pas, vom adăuga unul dintre nodurile care nu se află deja in listă
 +  * Se construieşte recursiv lanţul de lungime_lanţ + 1
 +  * Dacă dimensiunea listei este ''​n''​ (numărul de noduri din graf), se verifică dacă primul şi ultimul nod din listă sunt adiacente. În caz contrar, s-a găsit un lanţ hamiltonian,​ dar nu şi un ciclu hamiltonian.
 +  * Pentru a afla toate ciclurile hamiltoniene,​ la revenirea cu succes din apelul recursiv nu se iese din funcţie la găsirea primei potriviri, ci se încearcă în continuare alte posibilităţi.
  
-<​hidden>​ +=== Pseudocod ===
-Laboratoare vechi:+
  
-{{:​sd-ca:​laboratoare:​lab_8:​lab08.zip|}}+<​code>​ 
 +// Inițializări 
 +număr_noduri = număr de noduri din V
  
-{{:​sd-ca:​laboratoare:​lab_8:​lab8skel.zip|Schelet}}+// Verifica dacă un nod este nou în lanţ 
 +nouÎnLanţ(nod,​ lanţ) 
 +{ 
 +    return !lanţ.conţine(nod) 
 +}
  
-https://drive.google.com/​open?​id=1mCiLKlUPNAJORs5ebGDi0GK-M3kPJ2wQ+// Construieste lanţul hamiltonian 
 +construireLanţ(lanţ,​ lungime_lanţ) 
 +
 +    dacă lungime_lanţ == număr_noduri 
 +    { 
 +        început = lanţ[0] 
 +        sfârşit ​ultimul element din lanţ
  
-{{:​sd-ca:​laboratoare:​lab_8:​lab8skel.zip|Schelet}}+        // Există muchie între cele 2 noduri 
 +        dacă muchie(început,​ sfârşit) 
 +        ​{ 
 +            // Lanţul este ciclu 
 +            afişează ciclul 
 +            return true 
 +        ​} 
 +    ​} 
 +    altfel 
 +    { 
 +        pentru orice nod u din V 
 +        { 
 +            sfârşit = ultimul element din lanţ 
 +            dacă muchie(u, sfârşit) şi nouÎnLanţ(u,​ lanţ) 
 +            { 
 +                addLast(lanţ,​ u)    // Adaugă u la lanţ 
 +                 
 +                construireLanţ(lanţ,​ lungime_lanţ + 1)
  
-</hidden>+                ​// Pentru afişarea unui singur ciclu hamiltonian linia anterioară este inlocuită cu: 
 +                // dacă construireLanţ(lanţ,​ lungime_lanţ + 1) == true 
 +                //       ​return true 
 +                 
 +                removeLast(lanţ,​ u) // Backtrack 
 +            } 
 +        } 
 +    } 
 +    return false 
 +}
  
 +// Apelează construirea ciclurilor hamiltoniene
 +cicluriHamiltoniene
 +{
 +    // Din moment ce ar trebui să formeze un ciclu, lanţul poate incepe cu orice nod
 +    sursă = alegem un nod aleator din V
 +    addLast(lanţ,​ sursă)
 +    construireLanţ(lanţ,​ 1)
 +}
 +</​code>​
  
-===== Exerciții ===== 
  
 +=== Exemplu ===
 +
 +{{sd-ca:​laboratoare:​hamilton.png}}
 +
 +===== Schelet =====
 <note important>​ <note important>​
-Pentru a rezolva laboratorul folosind ​Github Classroom, ​urmați [[sd-ca:​laboratoare/​tutorial-github-classroom#​adaugarea_solutiei_unui_laborator|acești pași]]Asigurați-vă ca ați creat branchul pentru acest laborator **din branchul ''​master''​** al repository-ului vostru.+Daca folositi **Github Classroom**va rugam sa va actualizati scheletul cu cel de mai josCel din repo-ul clonat initial nu este la cea mai recenta versiune.
 </​note>​ </​note>​
  
-1) [**4p**] Implementați,​ compilați si testați funcțiile din //​**binary_tree.c**//​.+{{:​sd-ca:​laboratoare:​lab07_2024.zip|Scheletul de laborator}}
  
-Inserarea se va face recursiv, pe prima poziție liberă găsită.+===== Exerciții =====
  
-**311CAa**) ​[**3p**Calculați înălțimea arborelui.+<​note>​ 
 +Trebuie să vă creați cont de [[https://​code.devmind.ro/​ | Devmind]], dacă nu v-ați creat deja, pe care îl veți folosi la SD pe toată durata semestruluiAveti grija sa selectati contestul corect la submit, si anume **[[https://​beta.lambdachecker.io/​contest/​34 |SD-CA-LAB-11 Grafuri (Advanced) ]]** 
 +</​note>​
  
-**311CAb**) [**3p**] Verificați dacă toate frunzele din arbore se află pe același nivel.+1) [**3.5p**] Rezolvați problema **Connected Components**.
  
-**312CAa**) [**3p**] Fiind dat un arbore binar ale cărui noduri reţin valori întregi, verificați dacă valoarea din fiecare nod este egală cu suma valorilor copiilor săi. 
  
-**312CAb**) [**3p**] Verificați dacă arborele este echilibrat.+2) [**3.5p**] Rezolvați problema **Minimum Path**.
  
-**313CAa**) [**3p**] Fiind dat un număr natural n, afişaţi toate nodurile de pe nivelul n din arbore. 
  
-**313CAb**) [**3p**] Se dau două noduri A şi B din acelaşi arbore. Determinaţi cel mai jos strămoş comun al celor două noduri (LCA).+3) [**3p**] Rezolvati problema ​**Check Bipartite**.
  
-**314CAa**) [**3p**] Afișați toate drumurile de sumă maximă din rădăcină până într-una dintre frunze. 
  
-**314CAb**) [**3p**] Un arbore binar complet este un arbore binar în care fiecare nivel, cu posibila excepţie a ultimului nivel, este plin de noduri. Cu alte cuvinte, fiecare nivel este “umplut” de la stânga la dreapta cu noduri, iar ultimul nivel poate să nu fie umplut până la capăt. 
-Fiind dat un arbore binar, determinaţi dacă acesta este complet. 
  
-**315CAa**) [**3p**] Găsiți un subarbore cu suma nodurilor maximă. 
  
-**315CAb**) [**3p**] Fiind dat un arbore binar ale cărui noduri reţin valori întregi, verificaţi dacă pentru fiecare nod din arbore este adevărat faptul că valoarea sa este mai mare decât valoarea copilului stâng şi mai mică decât valoarea copilului drept.+===== Bibliografie =====
  
-**Bonus** ​[**2p**] Eliberați memoria unui arbore binar în O(1memorie, adică fără a folosi recursivitate sau prea multe variabile declarate cu acest scop. +    - [[http://​en.wikipedia.org/​wiki/​Connected_component_(graph_theory| Componente conexe ]] 
- +    - [[http://​en.wikipedia.org/​wiki/​Shortest_path | Distanţa minimă ]] 
-<​hidden>​ +    - [[http://en.wikipedia.org/​wiki/​Topological_sorting | Sortare topologică ]] 
-311CAb: exista mai multe metode, dintre care stiu 2+    - [[https://en.wikipedia.org/wiki/Bipartite_graph | Graf bipartit ]] 
-  * Se calculeaza distanta fiecarei frunze fata de rootDaca toate frunzele sunt la aceeasi distanta fata de root, frunzele sunt toate la acelasi nivelDaca exista doua distante diferite ale frunzelor fata de root, frunzele nu sunt toate la acelasi nivel +    [[https://​en.wikipedia.org/​wiki/​Hamiltonian_path | Lanţ hamiltonian si ciclu hamiltonian ]] 
-  ​* ​https://www.geeksforgeeks.org/check-leaves-level+    - [[http://​en.wikipedia.org/​wiki/​Dijkstra%27s_algorithm | Dijkstra ]] 
-</​hidden>​ +    ​- [[http://en.wikipedia.org/​wiki/​Bellman-ford | Bellman-Ford ]] 
- +    ​- [[http://en.wikipedia.org/​wiki/​Floyd%E2%80%93Warshall_algorithm | Floyd-Warshall ]] 
-===== Interviu ===== +    - [[http://en.wikipedia.org/​wiki/​A*_search_algorithm | A* ]]
- +
-Această secțiune nu este punctată și încearcă să vă facă o oarecare idee a tipurilor de întrebări pe care le puteți întâlni la un job interview (internship,​ part-time, full-time, etc.) din materia prezentată în cadrul laboratorului. +
- +
-    *Ce este un arbore? +
-    ​*Cum poate fi reprezentat un nod dintr-un arbore binar? +
-    ​*Daţi exemplu de un tip (mai multe tipuri) de parcurgere al arborilor binariDescrieţi modul de funţionare al acestuia (acestora)+
-    ​*Daţi exemplu de un mod de utilizare al arborilor binari+
-    ​*Ce complexitate medie / worst-case au funcţiile de inserare ​ştergere ​căutare pentru un arbore binar, BST, AVL, etc(mai multe despre complexitatea algoritmilor şi structurilor de date veţi învăţa în anul 2: Analiza Algoritmilor şi Proiectarea Algoritmilor). +
- +
-===== Bibliografie =====+
  
-    - [[http://​en.wikipedia.org/​wiki/​Binary_tree | Binary Tree]] 
-    - [[http://​en.wikipedia.org/​wiki/​AVL_tree | AVL ]] 
-    - [[http://​en.wikipedia.org/​wiki/​Red%E2%80%93black_tree | Red-Black Tree ]] 
-    - [[https://​en.wikipedia.org/​wiki/​Segment_tree | Arbori de Intervale ]] 
-    - [[https://​en.wikipedia.org/​wiki/​Fenwick_tree | Arbori Indexati Binar ]] 
-    - [[http://​en.wikipedia.org/​wiki/​Splay_tree | Splay Tree ]] 
-    - [[http://​en.wikipedia.org/​wiki/​Abstract_syntax_tree | AST ]] 
-    - [[http://​en.wikipedia.org/​wiki/​Disjunctive_normal_form | DNF ]] 
sd-ca/laboratoare/lab-08.1651072795.txt.gz · Last modified: 2022/04/27 18:19 by radu_stefan.minea
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