Differences

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

Link to this comparison view

sd-ca:laboratoare:lab-08 [2024/04/26 03:05]
radu.nichita [Exerciții]
sd-ca:laboratoare:lab-08 [2026/05/11 22:09] (current)
valentin.carauleanu [Interviu]
Line 1: Line 1:
-====== Laborator ​Arbori Binari ​======+====== Laborator ​11 Grafuri - Advanced  ​======
  
-Responsabili: +Responsabili 
-  * [[mailto:​popaiarina13@gmail.com|Iarina-Ioana Popa]] +  * [[stef.dascalu@gmail.com|Ștefan-Teodor Dascălu]] 
-  * [[mailto:​andreipirlea03@gmail.com|Andrei Pîrlea]]+  * [[melih.riza03@gmail.com|Melih Riza]] 
 +  * [[valentin.carauleanu@stud.fim.upb.ro|Cărăuleanu Valentin Gabriel]]
  
 ===== 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ărinte, iar acesta este întotdeauna ​**rădăcina arborelui** (**root**).+Se numește ​**componentă conexă** a unui graf neorientat ''​G = (V, E)''​ un subgraf ''​G1 = (V1, E1)''​ în care pentru orice pereche de noduri ''​(A,​ B)''​ din ''​V1''​ există un lanț de la ''​A''​ la ''​B''​ și implicit de la ''​B''​ la ''​A''​.
  
-Un **arbore binar** este un caz special de arboreîn care fiecare nod poate avea maxim **doi descendenţi**: +<​note>​ 
-  *nodul stâng +**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''​ ar fi componenta conexă, iar ''​G1''​ nu. 
-  *nodul drept.+</​note>​
  
-Î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şanume pentru a reprezenta şi evalua expresii logice+  * Atât o parcurgere **BFS**cât șuna **DFS**, pornind dintr-un nod ''​A'',​ va determina componenta conexă din care face parte ''​A''​
-==== Reprezentarea arborilor binari ====+  * Pentru a determina toate componentele conexe ale unui graf ''​G ​(V, E)'',​ se parcurg toate nodurile din ''​V''​. 
 +  * Din fiecare nod care nu face parte dintr-o componentă conexă găsită anterior se pornește o nouă 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.+=== Complexitate ===
  
-<code c binary_tree.h>​ +^ Complexitate ^ Reprezentare prin liste de adiacență ^ Reprezentare prin matrice de adiacență ^ 
-typedef struct b_node_t b_node_t; +**Timp**     | ''​O(|V| + |E|)''​ | ''​O(|V|²)''​ | 
-struct b_node_t { +**Spațiu*  | ''​O(|V| + |E|)''​ | ''​O(|V|²)''​ |
-    /left child *+
-    b_node_t ​*left; +
-    /right child *+
-    b_node_t ​*right;+
  
-    /* data contained by the node */ +=== Pseudocod ===
-    void *data; +
-};+
  
-typedef struct b_tree_t b_tree_t; +<​code>​ 
-struct b_tree_t { +// Inițializări 
-    ​/* root of the tree *+pentru fiecare nod u din V 
-    ​b_node_t *root; +{ 
-     +    ​stare[u] = nevizitat 
-    ​/* size of the data contained by the nodes */ +
-    size_t data_size; +componente_conexe = 0
-}; +
-</​code>​+
  
-Structura nodului ​de mai sus este clară: +// Funcție ​de vizitare a nodului 
-  * pointer către fiul stâng +vizitare(nod) 
-  * pointer către fiul drept +{ 
-  * pointer către date+    ​stare[nod] = vizitat 
 +    ​printeaza nod 
 +}
  
-Pentru a ne reaminti cum alocăm/dealocăm memorie: +// Parcurgerea în adâncime 
-<code c> +DFS(nod) 
-/** +{ 
- * Creates a new binary tree +    ​stiva ​s
- * @data_size: size of the data contained by the tree'nodes +
- * @return: pointer to the newly created tree +
- */ +
-b_tree_t *b_tree_create(size_t data_size);+
  
-/** +    vizitare(nod) 
- * Clear the whole memory used by the tree and its nodes +    ​s.introdu(nod) 
- * @b_tree: the binary tree to be freed + 
- * @free_data: function used to free the data contained by a node +    cât timp stiva s nu este goală 
- */ +    { 
-void b_tree_free(b_tree_t *b_tree, void (*free_data)(void *));+        ​nodTop = nodul din vârful stivei 
 + 
 +        vecin = află primul vecin nevizitat al lui nodTop 
 +        dacă vecin există 
 +        { 
 +            vizitare(vecin) 
 +            s.introdu(vecin) 
 +        } 
 +        altfel 
 +        { 
 +            s.scoate(nodTop) 
 +        } 
 +    } 
 +
 + 
 +// Parcurgerea nodurilor din V 
 +pentru fiecare nod u din V 
 +
 +    dacă stare[u] == nevizitat 
 +    { 
 +        componente_conexe = componente_conexe + 1 
 +        DFS(u) 
 +    } 
 +}
 </​code>​ </​code>​
  
-De exempludacă dorim să creem un arbore binar ce conține elemente ​de tip *char*codul arată astfel+=== Exemplu === 
-<code c> + 
-b_tree_t ​*char_tree = b_tree_create(sizeof(char));​+Graful din imagine are 4 componente conexe. 
 + 
 +{{sd-ca:​laboratoare:​componenteConexe.png?​400}} 
 +==== Aflarea distanței minime între două noduri ==== 
 + 
 +Dacă toate muchiile au același costputem 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. Deoarece BFS descoperă nodurile în ordinea crescătoare a distanței față de sursă, nivelul nodului ''​B''​ în parcurgere corespunde distanței minime între ''​A''​ și ''​B''​. 
 + 
 +Pentru a reține distanța și drumul exact de la ''​A''​ la ''​B''​se păstrează pentru fiecare nod
 +  * ''​d[x]''​ - distanța de la sursă la nodul ''​x''​ 
 +  ''​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 fac atribuirile:​
  
-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 ==== +<note important>​ 
-  *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'',​ deci distanța este infinită. 
-  *Se parcurge subarborele ​**stâng** +  * Algoritmul funcționează corect ​**numai pentru grafuri cu cost uniform** (toate muchiile au același cost). Pentru grafuri cu muchii de costuri diferite sunt necesari algoritmi mai avansați: ​**Dijkstra****Bellman-Ford** sau **Floyd-Warshall**. 
-  ​*Se parcurge subarborele ​**drept**+</​note>​
  
-==== 2. Inordine ====+=== Complexitate ​===
  
-  *Se parcurge subarborele **stâng** +^ Complexitate ^ Reprezentare prin liste de adiacență ^ Reprezentare prin matrice de adiacență ^ 
-  *Se parcurge ​**rădăcina** +**Timp**   | ''​O(|V| + |E|)''​ | ''​O(|V|²)''​ | 
-  *Se parcurge subarborele ​**drept**+**Spațiu** | ''​O(|V| + |E|)''​ | ''​O(|V|²)''​ |
  
-Exemplu: +=== Pseudocod ===
-<code c> +
-void b_tree_print_inorder(b_node_t *b_node, void (*print_data)(void *)) { +
-    if (!b_node) +
-        return;+
  
-    b_tree_print_inorder(b_node->left, print_data);​ +<code> 
-    ​print_data(b_node->​data);​ +// Inițializări 
-    ​b_tree_print_inorder(b_node->​right,​ print_data);​+pentru fiecare nod u din V 
 +{ 
 +    ​stare[u] = nevizitat 
 +    ​d[u] = infinit 
 +    p[u] = null
 } }
-</​code>​ 
-==== 3. Postordine ==== 
  
-  *Se parcurge subarborele **stâng** +// Distanța între sursă și destinație 
-  *Se parcurge subarborele **drept** +distanta(sursa,​ destinatie) 
-  *Se parcurge **răcina**+
 +    stare[sursa] = vizitat 
 +    ​d[sursa] = 0 
 +    enqueue(Q, sursa) ​              // Punem nodul sursă în coada Q
  
-==== 4. Lățime ====+    // 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[destinatie] ​           // Dacă este infinit, nu există drum 
 +
 +</​code>​ 
 +==== Sortarea topologică ====
  
-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ângrespectiv drept al nodului scos. Acest algoritm continuă până când coada devine goală.+Se dă un graf orientat aciclic (**DAG** - Directed Acyclic Graph). 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ă ''​(uv)''​ este una dintre muchiile grafului, ''​u''​ apare înaintea lui ''​v''​ în înșiruire.
  
 <note important>​ <note important>​
-Nodurile frunză nu au descendenţi -> nodul stâng şi nodul drept pointează la **NULL** şi nu trebuie adăugate în coadă.+Dacă graful este ciclic, sortarea topologică **nu este posibilă**, deoarece ​nu se poate stabili o ordine între nodurile care alcătuiesc un ciclu.
 </​note>​ </​note>​
  
-==== Arbori asociați expresiilor ====+Sortarea topologică poate fi vizualizată ca plasarea nodurilor de-a lungul unei linii orizontale astfel încât toate muchiile să fie orientate de la stânga la dreapta, fără nicio muchie îndreptată înapoi spre un părinte.
  
-O expresie matematică este un şir de caractere compus din: +=== Algoritm ===
-  *variabile +
-  *constante +
-  *operatori +
-  *paranteze (eventual).+
  
-Fiecărei expresii i se poate asocia un arbore binar, în care: +Sortarea topologică se realizează printr-o parcurgere **DFS**, în care se rețin pentru fiecare nod
-  *nodurile interioare reprezintă **operatorii** +  * ''​tDesc[u]''​ - momentul descoperirii nodului ''​u''​ 
-  *frunzele reprezintă **constantele** şi/sau **variabilele**.+  * ''​tFin[u]''​ - momentul finalizării procesării nodului ''​u''​
  
-În terminologia limbajelor formale şi a compilatoareloracest arbore se mai numeşte şi **Abstract Syntax Tree (AST)**.+La finalnodurile sunt sortate ​**descrescător** după ''​tFin''​. Nodul care se finalizează cel mai târziu trebuie să apară primul în sortare, deoarece nu depinde de niciun alt nod nedescoperit încă.
  
-Pentru expresia **(a+1)*(b+10)+25/​c** , arborele asociat este prezentat mai jos: +=== Complexitate ===
-{{ sd-ca:​laboratoare:​imagine-ast.png?​nolink&​600 |}}+
  
-<​hidden>​ +^ Complexitate ^ Reprezentare prin liste de adiacență ^ Reprezentare prin matrice de adiacență ^ 
-==== Evaluarea expresiilor ====+^ **Timp** ​  | ''​O(|V| + |E|)''​ | ''​O(|V|²)''​ | 
 +^ **Spațiu** | ''​O(|V| + |E|)''​ | ''​O(|V|²)''​ |
  
-Următorul pseudo-cod reprezintă în linii mari algoritmului de evaluare a expresiilor reprezentate sub formă de arbori binari: +=== Pseudocod === 
-  + 
-<​code ​c+++<​code>​ 
-Evalueaza(Node ​nod+// Inițializări 
-    ​// Daca nu este nod terminal... +pentru fiecare ​nod u din V 
-    ​if (nod->​left || nod->​right) { +
-        // Evaluam expresiile subarborilor... +    ​stare[u] = nevizitat 
-        ​res1 ​Evalueaza(nod->​left);​ +    ​p[u] = NULL 
-        ​res2 ​Evalueaza(nod->​right);​ +    ​tDesc[u] = 0 
-         +    ​tFin[u] ​0 
-        // ... si combinam rezultatele aplicand operatorul +
-        ​return AplicaOperator(nod->op, res1, res2); +contor_timp ​0 
-   } else + 
-        // Daca nodul terminal contine o variabila, atunci intoarcem valoarea variabilei +// Funcție de vizitare a nodului 
-        ​if ​(nod->var) { +vizitare(nod) 
-            ​return Valoare(nod->var); +
-        ​} else // Avem o constanta +    ​contor_timp = contor_timp + 1 
-            ​return ​nod->val;+    tDesc[nod] = contor_timp 
 +    stare[nod] = vizitat 
 +    printeaza nod 
 +
 + 
 +// Parcurgere în adâncime (recursiv) 
 +DFS(nod) 
 +
 +    ​vizitare(nod) 
 +    pentru fiecare vecin al lui nod 
 +    { 
 +        dacă stare[vecin] == nevizitat 
 +        { 
 +            ​p[vecin] = nod 
 +            DFS(vecin)
         }         }
-   }+    ​} 
 +    contor_timp = contor_timp + 1 
 +    tFin[nod] = contor_timp
 } }
 +
 +// Parcurgere noduri și calculare tDesc și tFin pentru fiecare nod
 +pentru fiecare nod u din V
 +{
 +    dacă stare[u] == nevizitat
 +    {
 +        DFS(u)
 +    }
 +}
 +
 +// Sortare topologică
 +sortează nodurile din V descrescător în funcție de tFin[nod]
 </​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|}}+Profesorul Bumstead își sortează topologic hainele înainte de a se îmbrăca: 
 +  * Fiecare muchie ''​(u,​ v)''​ înseamnă că obiectul de îmbrăcăminte ''​u''​ trebuie îmbrăcat înaintea obiectului ''​v''​. Timpii de descoperire ''​tDesc''​ și de finalizare ''​tFin''​ sunt notați lângă fiecare nod. 
 +  * Același graf, sortat topologicnodurile sunt aranjate de la stânga la dreapta în ordinea descrescătoare a ''​tFin'',​ astfel toate muchiile sunt orientate de la stânga la dreapta.
  
-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.+{{sd-ca:​laboratoare:​topologie.jpg?500}}
  
 +Sortarea topologică constă în sortarea nodurilor **descrescător după timpii de finalizare**. Nodul care se finalizează cel mai târziu nu depinde de niciun alt nod rămas, deci trebuie plasat primul în ordine topologică.
 +==== Graf bipartit ====
  
-===== Schelet ​=====+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 ∪ B''​ și ''​E ⊆ A × B''​. 
 + 
 +Altfel spus, nodurile grafului se pot împărți în 2 mulțimi astfel încât **nu** există muchii între noduri din aceeași mulțime. 
 + 
 +<note info>​Observație:​ Un graf nu este **bipartit** dacă conține un **ciclu de lungime impară**. 
 +</​note>​ 
 + 
 +=== Algoritm ​=== 
 + 
 +  * Pentru a determina dacă un graf este bipartit, una din metode constă în efectuarea unei parcurgeri **BFS** și atribuirea de etichete nodurilor în funcție de paritatea nivelului acestora: ''​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 verifică și etichetele vecinilor deja vizitați: dacă un vecin deja vizitat are **aceeași etichetă** ca nodul curent, înseamnă că există o muchie între noduri de pe același nivel, deci graful **nu este bipartit**. 
 +  * În caz contrar, dacă parcurgerea BFS se finalizează fără a apărea această situație, graful este bipartit și nodurile sunt etichetate cu mulțimea din care fac parte. 
 +  * Nodurile izolate pot fi atribuite oricăreia dintre cele două mulțimi, deci **nu afectează bipartitivitatea** grafului. 
 + 
 +=== Complexitate === 
 + 
 +^ Complexitate ^ Reprezentare prin liste de adiacență ^ Reprezentare prin matrice de adiacență ^ 
 +^ **Timp** ​    | ''​O(|V| + |E|)'' ​ | ''​O(|V|²)''​| 
 +^ **Spațiu** ​  | ''​O(|V|)''​ | ''​O(|V|)'' ​ | 
 + 
 + 
 +=== Pseudocod === 
 + 
 +<​code>​ 
 +cât timp încă sunt noduri nevizitate 
 +
 +    n = primul nod nevizitat 
 + 
 +    nivel[n] = par 
 +    enqueue(Q, n)        // 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ă nivel[u] nedefinit 
 +            { 
 +                nivel[u] = (nivel[v] == par) ? impar : par 
 +                enqueue(Q, u)    // Adăugăm nodul u în coadă 
 +            } 
 +            altfel dacă nivel[u] == nivel[v] 
 +            { 
 +                // Două noduri adiacente au același nivel 
 +                // Graful nu este bipartit 
 +                return false 
 +            } 
 +        } 
 +    } 
 +
 +// Parcurgerea BFS s-a finalizat fără noduri adiacente pe același nivel 
 +// Graful este bipartit 
 +return true 
 +</​code>​ 
 + 
 +=== Exemplu === 
 + 
 +{{sd-ca:​laboratoare:​bipartite_realization.svg.png?​400}} 
 +==== 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, lanțul formează un **ciclu hamiltonian**. 
 + 
 +Un graf ce conține un ciclu hamiltonian se numește **graf hamiltonian**.
  
 <note important>​ <note important>​
-Daca folositi ​**Github Classroom**, va rugam sa va actualizati scheletul cu cel de mai jos. Cel din repo-ul clonat initial ​nu este la cea mai recenta versiune.+Problema găsirii unui ciclu hamiltonian este **NP-completă**, ceea ce înseamnă că nu se cunoaște niciun algoritm eficient (polinomial) pentru cazul general.
 </​note>​ </​note>​
  
-{{:​sd-ca:​laboratoare:​lab8_2022.zip|Scheletul de laborator}}+=== Algoritm ===
  
 +În cadrul acestui laborator, vom folosi metoda **backtracking** pentru găsirea unui ciclu hamiltonian. Se menține o listă în care sunt adăugate nodurile parcurse:
  
 +  * La fiecare pas, se adaugă unul dintre nodurile care nu se află deja în listă.
 +  * Se construiește recursiv lanțul de ''​lungime_lant + 1''​.
 +  * Dacă dimensiunea listei este ''​n'',​ se verifică dacă există o muchie de la ultimul nod din listă către primul. Dacă nu există o astfel de muchie, lanțul curent nu poate fi închis într-un ciclu hamiltonian și se continuă cu backtracking.
 +  * Pentru a afla **toate** ciclurile hamiltoniene,​ la revenirea din apelul recursiv nu se iese din funcție la prima potrivire, ci se încearcă în continuare alte posibilități.
 +
 +=== Complexitate ===
 +
 +^ Complexitate ^ Valoare ^
 +^ **Timp** ​  | ''​O(|V|!)''​ în cazul cel mai defavorabil |
 +^ **Spațiu** | ''​O(|V|)''​ pentru stiva de recursivitate și lanț |
 +
 +=== Pseudocod ===
 +
 +<​code>​
 +// Inițializări
 +numar_noduri = număr de noduri din V
 +
 +// Verifică dacă un nod este nou în lanț
 +nouInLant(nod,​ lant)
 +{
 +    return !lant.contine(nod)
 +}
 +
 +// Construiește lanțul hamiltonian
 +construireLant(lant,​ lungime_lant)
 +{
 +    dacă lungime_lant == numar_noduri
 +    {
 +        inceput = lant[0]
 +        sfarsit = ultimul element din lant
 +        // Verifică dacă există muchie de la sfarsit spre inceput
 +        dacă muchie(sfarsit,​ inceput)
 +        {
 +            afiseaza ciclul
 +            return true
 +        }
 +    }
 +    altfel
 +    {
 +        pentru orice nod u din V
 +        {
 +            sfarsit = ultimul element din lant
 +            // Verifică dacă există muchie de la sfarsit spre u
 +            dacă muchie(sfarsit,​ u) si nouInLant(u,​ lant)
 +            {
 +                addLast(lant,​ u)       // Adaugă u la lanț
 +
 +                construireLant(lant,​ lungime_lant + 1)
 +                // Pentru afișarea unui singur ciclu hamiltonian,​
 +                // linia anterioară se înlocuiește cu:
 +                // dacă construireLant(lant,​ lungime_lant + 1) == true
 +                //     ​return true
 +
 +                removeLast(lant,​ u)    // Backtrack
 +            }
 +        }
 +    }
 +    return false
 +}
 +
 +// Apelează construirea ciclurilor hamiltoniene
 +cicluriHamiltoniene()
 +{
 +    // Din moment ce formează un ciclu, lanțul poate începe cu orice nod
 +    sursa = alegem un nod aleator din V
 +    addLast(lant,​ sursa)
 +    construireLant(lant,​ 1)
 +}
 +</​code>​
 +
 +=== Exemplu ===
 +
 +{{sd-ca:​laboratoare:​hamilton.png?​400}}
 ===== Exerciții ===== ===== Exerciții =====
  
 <​note>​ <​note>​
-Trebuie să vă creați cont de [[https://lambdachecker.io Lambda Checker]], dacă nu v-ați creat deja, pe care îl veți folosi la SD pe toată durata semestrului. ​Aveti grija sa selectati contestul corect la submit, si anume **[[https://​beta.lambdachecker.io/​contest/​75/​problems |Laborator 8 SD]]**+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 semestrului.
 </​note>​ </​note>​
  
-1) [**4p**] Implementarea arborelui binarProblema ​**SD-CA-LAB-08-Binary-Tree** pe LambdaChecker.+1) [**3.5p**] Rezolvați problema **Connected Components**. 
 +2) [**3.5p**] Rezolvați problema **Minimum Path**. 
 +3) [**3p**] Rezolvați problema ​**Check Bipartite**.
  
-2) [**3p**] O problema **aleasa de catre asistent** din cele ramase.+===== Interviu =====
  
-3) [**Bonus**] 1p bonus pe fiecare problema (easy sau medium) in plus pe care o rezolvati, maxim 2p bonus pentru o problema **easy** si una **medium** sau 2 **medium**.+Această secțiune nu este punctată și încearcă să vă ofere o idee despre tipurile de întrebări ​pe care le puteți întâlni la un job interview din materia prezentată în cadrul laboratorului.
  
-===== Interviu =====+=== Probleme recomandate ​===
  
-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.+**Sortare topologică:** 
 +  * [[https://​leetcode.com/​problems/​course-schedule-ii/​description|210Course Schedule II]] (returnarea ordinii topologice efective) 
 +  * [[https://​leetcode.com/​problems/​longest-increasing-path-in-a-matrix/​description|329. Longest Increasing Path in a Matrix]] (DAG implicit pe matrice)
  
-    ​*Ce este un arbore? +**Componente conexe și grafuri bipartite:​** 
-    *Cum poate fi reprezentat un nod dintr-un arbore binar+  [[https://​leetcode.com/​problems/​is-graph-bipartite/​description|785. Is Graph Bipartite?]] (verificare bipartitivitate cu BFS/DFS) 
-    *Daţi exemplu de un tip (mai multe tipuride parcurgere al arborilor binariDescrieţi modul de funţionare al acestuia ​(acestora). +  [[https://​leetcode.com/​problems/​accounts-merge/​description|721. Accounts Merge]] ​(componente conexe cu Union-Find) 
-    *Daţi exemplu de un mod de utilizare al arborilor binari+  * [[https://​leetcode.com/​problems/​satisfiability-of-equality-equations/​description|990. Satisfiability of Equality Equations]] ​(componente conexe pe graf implicit) 
-    *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 2Analiza Algoritmilor şProiectarea Algoritmilor).+ 
 +**Drumuri minime:** 
 +  * [[https://​leetcode.com/​problems/​network-delay-time/​description|743. Network Delay Time]] (Dijkstra clasic) 
 +  [[https://​leetcode.com/​problems/​find-the-city-with-the-smallest-number-of-neighbors-at-a-threshold-distance/​description|1334. Find the City with the Smallest Number of Neighbors]] (Floyd-Warshall) 
 +  [[https://​leetcode.com/​problems/​cheapest-flights-within-k-stops/description|787. Cheapest Flights Within K Stops]] (Bellman-Ford cu constrângeri) 
 + 
 +**Probleme avansate:​** 
 +  * [[https://​leetcode.com/​problems/​reconstruct-itinerary/description|332Reconstruct Itinerary]] ​(circuit eulerian pe graf orientat) 
 +  * [[https://​leetcode.com/​problems/​critical-connections-in-a-network/​description|1192. Critical Connections in a Network]] (punțîn graf cu algoritmul Tarjan) 
 +  * [[https://​leetcode.com/​problems/​swim-in-rising-water/​description|778. Swim in Rising Water]] (BFS/​Dijkstra pe matrice cu cost variabil)
  
 ===== Bibliografie ===== ===== Bibliografie =====
  
-    - [[http://​en.wikipedia.org/​wiki/​Binary_tree ​Binary Tree]] +    - [[http://​en.wikipedia.org/​wiki/​Connected_component_(graph_theory) ​Componente conexe ​]] 
-    - [[http://​en.wikipedia.org/​wiki/​AVL_tree ​AVL ]] +    - [[http://​en.wikipedia.org/​wiki/​Shortest_path ​Distanţa minimă ​]] 
-    - [[http://​en.wikipedia.org/​wiki/​Red%E2%80%93black_tree ​Red-Black Tree ]] +    - [[http://​en.wikipedia.org/​wiki/​Topological_sorting ​Sortare topologică ​]] 
-    - [[https://​en.wikipedia.org/​wiki/​Segment_tree ​Arbori de Intervale ​]] +    - [[https://​en.wikipedia.org/​wiki/​Bipartite_graph ​Graf bipartit ​]] 
-    - [[https://​en.wikipedia.org/​wiki/​Fenwick_tree ​Arbori Indexati Binar ]] +    - [[https://​en.wikipedia.org/​wiki/​Hamiltonian_path ​Lanţ hamiltonian si ciclu hamiltonian ​]] 
-    - [[http://​en.wikipedia.org/​wiki/​Splay_tree ​Splay Tree ]] +    - [[http://​en.wikipedia.org/​wiki/​Dijkstra%27s_algorithm ​Dijkstra ​]] 
-    - [[http://​en.wikipedia.org/​wiki/​Abstract_syntax_tree ​AST ]] +    - [[http://​en.wikipedia.org/​wiki/​Bellman-ford ​Bellman-Ford ​]] 
-    - [[http://​en.wikipedia.org/​wiki/​Disjunctive_normal_form ​DNF ]]+    - [[http://​en.wikipedia.org/​wiki/​Floyd%E2%80%93Warshall_algorithm ​Floyd-Warshall ​]] 
 +    - [[http://​en.wikipedia.org/​wiki/​A*_search_algorithm | A* ]] 
sd-ca/laboratoare/lab-08.1714089932.txt.gz · Last modified: 2024/04/26 03:05 by radu.nichita
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