Differences

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

Link to this comparison view

sd-ca:laboratoare:lab-11 [2020/05/14 02:01]
teodor_stefan.dutu [Noțiuni de bază despre AVL Trees] Corectare imagini cu rotatii
sd-ca:laboratoare:lab-11 [2023/05/16 14:52] (current)
iulia.corici [Exerciții]
Line 1: Line 1:
-====== Laborator 11 - AVL & Red-Black Trees ======+====== Laborator 11 - Arbori generici. Trie ======
  
 Responsabili Responsabili
-    ​* [[mailto:topala.andrei@gmail.com|Andrei Topală]] +  ​* [[mailto:coriciiulia76@gmail.com|Iulia Corici]] 
-    * [[mailto:doringeman@gmail.com|Dorin-Andrei Geman]]+  * [[mailto:becheanudaniela04@gmail.com|Daniela Becheanu]] 
 ===== Obiective ===== ===== Obiective =====
  
 În urma parcurgerii articolului,​ studentul va fi capabil să: În urma parcurgerii articolului,​ studentul va fi capabil să:
-  * înțeleagă ​conceptul unui arbore echilibrat ​de căutare +  * înţeleagă ​noţiunea ​de arbore generic 
-  * exemplifice acest concept pe structurile AVL & Red-Black +  * înţeleagă noţiunea şi structura unui trie 
-  * își sedimenteze informațiile despre arbori echilibrați și aplicațiile acestora +  * construiască, în limbajul C, un trie 
-===== Noțiuni de bază despre AVL Trees =====+  * utilizeze un trie
  
-  * arbore binar de căutare echilibrat după înălțime 
-  * arborele se reechilibrează(rebalancing) după fiecare inserare sau ștergere 
  
-Diferență între 2 subarbori ai oricărui nod este maxim 1. Se definește:​ +===== Arbori generici =====
-  * factor_de_balans(nod) ​înălțime(subarbore_drept(nod)) - înălțime(subarbore_stang(nod)) +
-  * invariant ​factor_de_balans(nod) este -1, 0 sau 1+
  
-Avantajul unui AVL Tree este faptul că produce cel mai echilibrat arbore ​în cazul cel mai defavorabil. Fiind perfect balansat, arborele AVL va scoate cel mai mic timp de utare dintre toţi ceilalţi arboriDezavantajul său este numărul mai mare de rotaţii pe care îl efectuează.+Până acum am studiat arbori binari, ​în cadrul ​rora un nod avea cel mult 2 fiiGeneralizarea arborilor binari ​este reprezentată de arborii generici, denumiți și //k-ary trees//, întrucât, în cadrul acestora, un nod poate avea cel mult k fii.
  
-<​note>​  +{{:sd-ca:​laboratoare:​generic_tree.png?600|}}
- Înălţimea unui AVL cu n noduri în cazul cel mai defavorabil este [[http://lcm.csa.iisc.ernet.in/​dsa/​node112.html ​1.44 * log(n)]]. +
-</​note>​+
  
-{{ sd-ca:​laboratoare:​AVL-tree-wBalance_K.svg.png?500 }}+În exemplul de mai sus, putem observa un 6-ary tree, unde nodurile pot avea cel mult 6 fii observăm astfel noduri cu 0, 1, 2 sau 6 fii.
  
-La inserare se adaugă nodul astfel încât să aibă proprietatea ​de arbore +Schelet minimal de structură de arbore ​generic:
-binar de căutare, iar după se verifică factorul de balansare și se începe sau +
-nu balansarea lui. Balansarea lui se face cu rotații duble.+
  
-  *[[https://​en.wikipedia.org/​wiki/​AVL_tree#​Simple_rotation | Rotatie simpla L]]  +<code c generic_tree.h> 
-  *[[https://​en.wikipedia.org/​wiki/​AVL_tree#​Double_rotation | Exemplu de rotatie RL]]+typedef struct g_tree_t g_tree_t; 
 +struct g_tree_t 
 +
 +    g_node_t ​*root; 
 +};
  
-Cele 4 tipuri de rotații (LL LR RL RR): 
-    * dacă factorul de balans este pozitiv 
-      * dacă factorul de balans al nodului stâng este pozitiv 
-        * Rotaţie LL (Left): rotire spre stânga 
  
 +typedef struct g_node_t g_node_t;
 +struct g_node_t ​
 +{
 +    void *value;
 +    g_node_t **children;
 +    int n_children;
 +};
 +</​code>​
  
-{{:​sd-ca:​laboratoare:​rr_rotation.png?500}}+===== De ce trie=====
  
 +O particularizare a arborilor generici este dată de Trie. Cunoscut și sub numele de arbore de prefixe (prefix tree), trie-ul este un arbore de căutare care permite operații de inserare și căutare de elemente in complexitate O(L) (L - lungimea cheii). ​
  
-      ​dacă factorul ​de balans al nodului stâng este negativ +De obicei trie-ul este folosit pentru a stoca string-uri și valori asociate acestora. Pe parcursul semestrului am studiat alte 2 structuri de date care pot efectua aceleași operații: hashtable-ul si arborele binar de căutare. De ce am studia înca o structură de date care poate realiza aceleași operații? Să comparăm Trie-ul cu: 
-        Rotaţie LR (Left-Right): rotire spre stânga + rotire spre dreapta+  ​*** ABC:** Trie-ul poate insera și căuta elemente in O(L), având o complexitate mai bună decât un arbore binar de căutare balansat O(logN) (ținând cont că în general lungimile cuvintelor sunt mult mai mici decât numărul de cuvinte stocate). 
 +  *** Hashtable:​** Pentru toate operațiile sale, trie-ul are o performanță comparabilă ​(uneori mai bună) față de un hashtable.  
 +  * Față de ambele structuri, trie-ul permite operații de căutare mai avansate, putând efectua căutari eficiente după prefix sau pentru cuvinte cu un număr de caractere lipsă sau greșite (autocomplete).
  
 +Care este dezavantajul acestei structuri?
 +  * Memoria utilizată variază în funcție de prefixele pe care le au in comun, însă în cazul cel mai defavorabil,​ numărul de noduri este egal cu suma lungimilor cheilor.
  
-{{:​sd-ca:​laboratoare:​lr_rotation.png?500}}+===== Ce este un trie=====
  
 +Un trie este o structură de tip arbore care reține asocieri de tip cheie - valoare. Cheia este reprezentată în general de un cuvânt sau un prefix al unui cuvânt, dar poate fi orice listă ordonată (ex: reprezentarea binară a numerelor - bitwise trie)
  
-    * dacă factorul de balans este negativ +Rădăcina utilizează pe post de cheie un string vid (""​). Diferența de lungime dintre cheia asociată unui nod și cheile copiilor săi este de 1. Astfel, copiii rădăcinii sunt noduri cu chei de dimensiune 1, iar copiii acestora au chei de dimensiune 2, etc.
-      * dacă factorul ​de balans al nodului drept este pozitiv +
-        * Rotire RL (Right-Left): rotire spre dreapta + rotire spre stânga+
  
 +În concluzie, putem spune că pentru un nod aflat la distanța k de radacină, acesta are o cheie de lungime k. De asemenea, dacă nodul n1 este strămoș al lui n2 atunci cheia asociată lui n1 este prefix al cheii asociate lui n2.
  
-{{:​sd-ca:​laboratoare:​rl_rotation.png?​500}} ​+Puteți observa în desenul de mai jos cum arată un trieDe observat că nodurile ce conțin valori sunt colorate cu albastru (nodurile corespunzătoare cheilor "​in"​ și "​int"​ conțin și ele valori, chiar dacă nu sunt noduri frunză)
  
 +{{ sd-ca:​laboratoare:​trie2.png |}}
  
 +În desenul de mai sus, trie-ul poate fi asimilat cu implementarea unui dicționar (spre exemplu: DEX; cu intrări de forma //<​cuvânt : definiția cuvântului>//​),​ unde nodurile pot fi privite în felul următor:
  
-      * dacă factorul de balans al nodului drept este negativ +<​code>​ 
-        * Rotire RR (Right) : rotire spre dreapta+// ""​ reprezintă șirul vid
  
-{{:sd-ca:laboratoare:ll_rotation.png?500}}+"" ​""​ 
 +""​ 
 +""​ 
 +"​to"​ : "​expressing motion in the direction of (a particular location)."​ 
 +"​te"​ : ""​ 
 +"​it"​ : "used to refer to a thing previously mentioned or easily identified."​ 
 +"​in"​ : "​expressing the situation of something that is or appears to be enclosed or surrounded by something else."​ 
 +"​tea"​ : "a hot drink made by infusing the dried crushed leaves of the tea plant in boiling water."​ 
 +"​ted"​ : "turn over and spread out (grass, hay, or straw) to dry or for bedding."​ 
 +"​ten"​ : "​equivalent to the product of five and two; one more than nine; 10." 
 +"​int"​ : "​interior."​ 
 +"​into"​ : "​expressing movement or action with the result that someone or something becomes enclosed or surrounded by something else."
  
 +</​code>​
 +===== Implementare =====
  
 +Fiind un arbore, trie-ul va respecta formatul standard al acestei structuri de date, însa cheia nu este reținută în mod explicit. Fiecare nod reține un vector cu fiii săi.
  
-Puteți urmări încă un exemplu [[https://​www.gatevidyalay.com/avl-tree-avl-tree-example-avl-tree-rotation/|aici]].+<code c trie.h> 
 +typedef struct trie_node_t trie_node_t;​ 
 +struct trie_node_t { 
 +    ​/* Value associated with key (set if end_of_word = 1) */ 
 +    void* value;
  
-==== Reprezentarea unui AVL ====+    /* 1 if current node marks the end of a word, 0 otherwise */ 
 +    int end_of_word;​
  
-Structura de mai jos este cea folosită de noi pentru reprezentarea AVL-ului din scheletul de laborator. ​+    trie_node_t** children; 
 +    int n_children;​ 
 +};
  
-<code c avl.h> +typedef struct ​trie_t trie_t
-/** +struct ​trie_t ​
- * The AVL node struct definition +    ​trie_node_troot
- */ +     
-typedef struct ​avl_node_t avl_node_t+    ​/* Number of keys */ 
-struct ​avl_node_t ​+    int size;
- /left child - smaller key */ +
- avl_node_t ​  *left+
- /* right child - bigger key */ +
- avl_node_t ​  ​*right;+
  
- /* the key of the node which will also be used for sorting ​*/ +    ​/* Generic Data Structure ​*/ 
- char *key;+    int data_size;
  
- /* height of the node */ +    ​/* Trie-Specific,​ alphabet properties ​*/ 
- int height+    int alphabet_size
-};+    char* alphabet;
  
-/** +    ​/* Callback to free value associated with key, should be called when freeing ​*/ 
- ​* ​The AVL tree struct definition +    void (*free_value_cb)(void*)
- *+     
-typedef struct avl_tree_t avl_tree_t+    /* Optional - number ​of nodes, useful to test correctness ​*/ 
-struct avl_tree_t { +    int nNodes;
- /* root of the tree */ +
- avl_node_t *root;​ +
- +
- /* function used for sorting the keys */ +
- int (*cmp)(const void *key1, const void *key2);+
 }; };
 </​code>​ </​code>​
  
-<​note>​ +În cadrul implementării din laborator, fiecare nod conține un vector de dimensiunea alfabetului,​ reprezentând copiii nodului; iar cheile vor conține numai litere mici al alfabetului englez. Poziția unui nod in vectorul ​rintelui ​u este dată de poziția în alfabet ​literei prin care se diferențiază de cheia parintelui său. În exemplul de mai jos, nodul cu cheia "​the"​ este pe a 5-a poziție in vectorul de copii al nodului cu cheia "​th",​ deoarece '​e'​ este a 5-a litera din alfabet
- Observăm absenţa pointer-ului către nodul rinte, fapt ce ne va cere să lucrăm cu (**node) pentru ​putea efectua rotaţiile corespunzător+ 
-</​note> ​+{{ sd-ca:​laboratoare:​trie12.jpg?​420x380 |}}
  
 +Deși am spus că nodul cu  cheia ”the” este pe a 5-a poziție în vectorul de copii al nodului cu cheia ”th”, acesta pare, conform desenului de mai sus, să fie doar cel de-al doilea copil al nodului ”th”. Motivul este că ”th” reține o listă cu cei 26 de potențiali fii, însă 23 dintre aceștia sunt nuli, în vreme ce doar 3 dintre aceștia există (”a”, ”e”, ”i”).
  
-==== Inserare în AVL ====+==== Căutare ​====
  
-Inserarea unui nod într-un AVL se realizează în 2 etape şeste asemănătoare inserării unui nod pentru un Treap: +În cazul în care cheia are lungime 0, se reține valoarea asociată nodului șse întoarce true daca nodul curent reprezintă sfârșit ​de cuvânt, altfel ​se apelează recursiv metoda search ​pe nodul care continuă cheia rintelui săcu prima litera a cuvântului primit ca parametru.
- * Se adaugă ​nodul conform inserării într-un arbore binar de cautare: ​se caută poziţia de inserare ​pe baza comparaţiei dintre nod şi cheia nodului stâng / drept. +
- * Din locul unde am efectuat adăugarea până în rădăcină,​ se actualizează înălţimea fiecărui nod şi in cazul în care este necesar, se aplică operaţii de rotire pentru a stra proprietatea AVL-ului (diferenţa în modul dintre înalţimea nodului stâng şi întălţimea nodului drept este mai mică sau egală cu 1).+
  
-Mai jos avem pseudocodul pentru operaţia de inserare:+=== Pseudocod ===
  
 <​code>​ <​code>​
-void insert(nodcheie) { +search(keynode) { 
- +    if key == ""​ 
- if (nod == NULL) { +        // The value of the node is the searched one 
- node = create_node(cheie) +        ​return node->value 
- } else if (nod->cheie > cheie) { +           
- insert(nod->​left,​ cheie) +    ​nextNode = child corresponding to the first letter of the key 
- } else { +     
- insert(nod->​right,​ cheie) +    if nextNode does not exist 
- } +        ​return NULL 
- +     
- nod->​inaltime = 1 + max(intaltime(nod->​left)inaltime(nod->​right) +    return search(key without first letternextNode
- aplicare_rotiri()+
 } }
 </​code>​ </​code>​
  
-==== Ștergere ​====+==== Inserare ​====
  
-Operaţia de ştergere pentru o cheie dintr-un arbore AVL se aseamănă cu ştergerea unei chei dintr-un BSTVom elimina nodul pe care dorim să îl ştergem în momentul în care acesta ajunge la baza arborelui. Următorul pas este să reactualizăm înălţimile fiecărui nod şi să efectuăm rotiri atunci când este necesarAstfel, putem rezuma stergerea unui nod dintr-un AVL în 3 etape: ​+Dacă lungimea cheii este 0, am ajuns la nodul a cărui ​cheie se vrea a fi inserată. Altfel, se apelează recursiv metoda insert ​pe nodul a cărui cheie diferă de cheia părintelui ​u prin prima literă a cuvântului primit ca parametru.
  
-1. Căutarea cheii pe care dorim să o ştergem.+=== Pseudocod ===
  
-2. Ştergerea nodului cu cheia respectivă. Dacă nodul are 2 succesori, îl vom înlocui cu cel mai mare nod din subarborele stâng ​(sau cel mai mic nod din subarborele drept). Altfelnodul va fi înlocuit cu unul dintre succesorii săi nenuli (sau NULLîn cazul în care nodul este frunză).+<​code>​ 
 +insert(nodekeyvalue{  // Key is the rest of the initial key to be processed 
 +    if length of key == 0 
 +        node->​data = value 
 +        node->​end_of_word = true 
 +        return 
 +       
 +    nextNode = child corresponding to the first letter of the key 
 +   
 +    if nextNode does not exist 
 +        create nextNode ​      
 +        node->​n_children++ 
 +        nNodes++
  
-3. Reactualizarea înălţimilor şi realizarea rotaţiilor necesare. +    insert(nextNodekey without first lettervalue
- +
-Mai jos avem pseudocodul pentru operaţia de ştergere:​ +
- +
-<​code>​ +
-void avl_delete(nodcheie) { +
- if (nod == NULL) { +
- return +
-+
- if (nod->​cheie > cheie) { +
- avl_delete(node->​leftcheie) +
- } else if (nod->​cheie < cheie) { +
- avl_delete(node->​right,​ cheie) +
- } else { +
- if (node are 0 succesori) { +
- stergere(node) +
- return;​ +
- } else if (node are 1 succesor) { +
- node = succesor(node) +
- } else { +
- max_node = max_element(node->​left);​ +
- copy(node,​ max_node) +
- avl_delete(node->​left,​ max_node->​cheie) +
-    } +
-+
-  +
- nod->​inaltime = 1 + max(intaltime(nod->​left),​ inaltime(nod->​right)) +
- aplicare_rotiri()+
 } }
 </​code>​ </​code>​
-===== Noțiuni de bază despre Red-Black Trees ===== 
  
-Un arbore roșu-negru este un arbore binar de căutare care are un bit suplimentar pentru memorarea fiecărui nod: culoarea acestuia, care poate fi roșu sau negru. Prin restrângerea modului în care se colorează nodurile pe orice drum de la rădăcină la o frunză, arborii roșu-negru garantează că nici un astfel de drum nu este mai lung decât dublul lungimii oricărui alt drum, deci că arborele este aproximativ echilibrat.+==== Ștergere ====
  
-Un arbore binar de căutare este arbore roșu-negru dacă el îndeplineste următoarele proprietăți:+Metoda întoarce true dacă nodul poate fi șters ​de către părinte, fiindcă nu este prefixul vreunui cuvânt inserat ​și fals altfel. Dacă nodul curent este cel ce trebuie șters, se șterge valoarea asociată. În caz contrar, se apelează recursiv metoda remove pe nodul a cărui cheie are ca ultimă literă prima litera a cuvântului primit ca parametru.
  
-  * Fiecare nod este fie roșu, fie negru. +{{ :​sd-ca:​8c18e786-6c8a-4a10-ac5f-10ce3716795a.jpeg?​nolink&​750 |}}
-  * Fiecare frunză (nil) este neagră. +
-  * Dacă un nod este roșu, atunci ambii fii ai săi sunt negri. +
-  * Fiecare drum simplu de la un nod la un descendent care este frunza conține același număr de noduri negre.+
  
-{{ 800px-red-black_tree_example.svg.png }}+În desenul de mai sus, nodurile roșii reprezintă nodurile cu end_of_word = true (cuvinte integrale, de sine stătătoare,​ adică dacă inserăm ”Mihai” in Trie, doar nodul cu ”Mihai” va avea end_of_word = true, în vreme ce ”M”, ”Mi”, ”Mih”, ”Miha” vor avea end_of_word = false).
  
-Mai multe detalii, aici+Să facem o scurtă trecere prin cele 3 operații din desen
-  ​* [[https://medium.com/​@aleksandrasays/​colour-it-please-as-red-black-trees-a74af93b8561|Colour it please as Red-Black Trees]] +  ​- "​aa"​”aa” reprezintă un cuvânt (are end_of_word = true), însă are copii (”aa”->​n_children > 0), adică reprezintă un prefix pentru alte cuvinte inserate anterior in TrieAstfel, pur și simplu flag-ul de end_of_word de pe nodul ”aa” este trecut la false. 
-  ​* [[https://www.cs.auckland.ac.nz/​software/​AlgAnim/​red_black_op.html|Cormen,​ p269]] +  ​"​aacx":​ ”aacx” reprezintă un cuvânt, și nu are copii, deci se vor șterge nodurile recursiv, de jos în sus de la ”x” până la primul nod întâlnit (iarăși, de jos în sus, întrucât revenim din recursivitate) ce are copii (cel de-al doilea ”a” din ”aacx”) sau are end_of_word = true. 
-===== AVL vs Red-Black =====+  ​- "​aab"​similar ca mai sus.
  
-  * AVL permite căutări mai rapide - sunt echilibrați mai "​strict"​ +=== Pseudocod ===
-  * Red-Black este mai potrivit pentru multe inserări și ștergeri - mai puține rotiri necesare+
  
-Cu toate acesteaambele tipuri ​de arbori discutate ​in acest articol ​sunt foarte populare si folosite.+<​code>​ 
 +remove(nodekey) { 
 +    if length of key == 0 
 +        free value 
 +         
 +        if node->​end_of_word == true 
 +            node->​end_of_word = false 
 +             
 +            // if n_children > 0, then this node marks a prefix of an already existing key, so we shouldn'​t free it yet 
 +            return node->​n_children == 0  
 +         
 +        // remove was called on a key that doesn'​t exist 
 +        return false 
 +   
 +    nextNode = child corresponding to the first letter of the key 
 +   
 +    if nextNode exists and remove(nextNode,​ key without first letter) == true 
 +        delete nextNode 
 +        node->​n_children-- 
 +        nNodes-- 
 +         
 +        if node->​n_children == 0 and node->​end_of_word == false 
 +            // second condition is mandatory because an intermediary node could mark a valid key AND a prefix of the  
 +            // key we are currently deleting at the same time 
 +            return true 
 +                
 +    return false 
 +
 +</​code>​ 
 +<note important>​Observati ca functiile primesc ca si parametru o structura ​de tip **trie_node_t**,​ nu **trie_t**. Deci, pseudocodul de mai sus va trebui implementat ​in niste functii helper. Motivul pentru care acestea nu sunt incluse in schelet este acela ca puteti implementa **iterativ** daca doriti, fara sa mai fie nevoie de helpere.</​note>​
  
-Arborii Red-Black sunt foarte folosiți în cazuri generale, unde se descurcă binișor la toate capitolele, în timp ce arborii AVL sunt folosiți în domeniul bazelor de date, unde timpul pentru o căutare reprezintă un factor foarte important. 
- 
-Cazuri concrete unde este utilizat Red-Black Tree: 
-  * Java: TreeMap, TreeSet 
-  * C++ STL: map, multimap, multiset 
-  * Linux Kernel: [[https://​en.wikipedia.org/​wiki/​Completely_Fair_Scheduler|Completely Fair Scheduler]] 
- 
-[[https://​discuss.fogcreek.com/​joelonsoftware/​default.asp?​cmd=show&​ixPost=22948 | AVL Trees vs. Red-Black Trees]] 
- 
-==== Reprezentarea unui Red-Black ==== 
- 
-<code c rb_tree.h>​ 
-enum COLOR { 
- RED, 
- BLACK 
-}; 
- 
-/** 
- * The Red-Black node struct definition 
- */ 
-typedef struct rb_node_t rb_node_t; 
-struct rb_node_t { 
- /* parent - RB_NODE_NULL for root */ 
- rb_node_t ​  ​*parent;​ 
- /* left child - smaller key */ 
- rb_node_t ​  ​*left;​ 
- /* right child - bigger key */ 
- rb_node_t ​  ​*right;​ 
- 
- /* the sorting is based on key */ 
- void *key;​ 
- /* data contained by the node */ 
- void *data;​ 
- 
- /* color of the node */ 
- enum COLOR color;​ 
-}; 
- 
-/** 
- * The Red-Black tree struct definition 
- */ 
-typedef struct rb_tree_t rb_tree_t; 
-struct rb_tree_t { 
- /* root of the tree */ 
- rb_node_t *root;​ 
- 
- /* key size */ 
- size_t key_size; 
- 
-    /* data size */ 
-    size_t data_size;​ 
- 
- /* function used for sorting the keys */ 
- int (*cmp)(const void *key1, const void *key2); 
-}; 
-</​code>​ 
 ===== Schelet ===== ===== Schelet =====
  
-{{sd-ca:​laboratoare:​lab_11:​lab11.zip|Schelet}}+{{:sd-ca:​laboratoare:​lab11_2022_v2.zip|Scheletul de laborator}}
 ===== Exerciții ===== ===== Exerciții =====
  
-1) [**45p**] Completați funcția de reechilibrare și implementați funcțiile de inserare, căutare și ștergere pentru AVL. 
- 
-2) [**45p**] Completați părțile de cod care lipsesc din funcțiile din **rb_tree.c**. 
- 
-<​hidden>​ 
 <​note>​ <​note>​
-Fiecare laborator va avea unul sau doua exerciții publice si un pool de subiecte ascunsedin care asistentul poate alege cum se formeaza celelalte puncte ale laboratorului.+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/​39|Laborator 11 SD]]**
 </​note>​ </​note>​
  
 +1) [**7p**] Implementarea Trie-ului
  
-[**10p**] Exerciții comune: ​ +===== Interviu ===== 
- +Arborii generici ​si in special ​trie sunt structuri ​de date intalnite des la interviuri, in special la companii mari din afara precum GoogleFacebookAmazonetc
-1) [**5p**] Implementați funcțiile de inserare și căutare a unei chei în Trie +   ​Cum ați implementa ​funcționalitatea de auto-complete? 
- +   ​Cum ați sorta eficient ​un array de șiruri de caratere? 
-2) [**3p**] Implementați funcția de ștergere a unui nod din Trie +   ​Cum ati organiza ierarhic angajatii ​dintr-o companie? 
- +   ​Cata memorie foloseste ​un nod din Trie? Cum putem optimiza complexitatea spatiala (memoria) unui Trie?  
-3) [**2p**] Feedback +===== Bibliografie ​de bază =====
- +
- ​Implementați funcția startsWith care primeste un prefix ca parametru ​si intoarce true da exista un cuvant ​in trie care sa inceapa cu acel prefix, false in caz contrar. +
- +
-<​hidden>​ +
-311CAa +
-  * Implementați funcția findDuplicateColumns care găsește coloanele duplicate dintr-o matrice binară (valorile din matrice ​sunt doar 0 și 1). Matricea trebuie parcursă doar o singură dată. +
- +
-[**2p**] Bonus +
-313CAa +
-  * Implementați funcția findLongestWord care intoarce cel mai lung cuvant dintr-un trie ce se poate construi caracter cu caracter ​de catre alte cuvinte deja existente in arbore. Spre exempludaca in trie avem cuvintele “m”“my”“mys”“myse”, “myself”,​ functia va intoarce string-ul “myself”+
- +
-<​hidden>​ +
-312CAa +
-  ​Implementați funcția longestCommonPrefix care intoarce cel mai lung prefix comun al cuvintelor dintr-un trie.  +
- +
- +
-312CAb +
-  ​Implementați funcția startsWith care primeste ​un prefix ca parametru si intoarce true da exista un cuvant in trie care sa inceapa cu acel prefix, false in caz contrar. +
- +
- +
-<​hidden>​ +
-313CAa +
-  ​Implementați funcția findLongestWord care intoarce cel mai lung cuvant ​dintr-un trie ce se poate construi caracter cu caracter de catre alte cuvinte deja existente in arbore. Spre exemplu, daca in trie avem cuvintele “m”, “my”, “mys”, “myse”, “myself”,​ functia va intoarce string-ul “myself”. ​ +
- +
-<​hidden>​ +
-313CAb +
-  ​Implementați funcția mostFrequestWords care primeste ​un numar k ca parametru si intoarce un vector cu k cele mai frecvente cuvinte dintr-un set de string-uri. +
- +
-<​hidden>​ +
-314CAa +
-  * Implementați funcția sortWords care primeste un vector ​de string-uri ca si parametru si intoarce un vector cu acele cuvinte sortate lexicografic.  +
- +
-<​hidden>​ +
-314CAb +
-  * Implementați funcția autocomplete care primeste un prefix ca parametru si intoarce un vector cu toate cuvintele care incep cu acel prefix.  +
- +
-<​hidden>​ +
-315CAa +
-  * Implementați funcția longestCommonSuffix care intoarce cel mai lung sufix comun al cuvintelor dintr-un trie.+
  
-<​hidden>​ +    - [[https://​www.wikiwand.com/​en/​Trie | Trie]] 
-315CAb +    - [[http://​www.geeksforgeeks.org/​trie-insert-and-search/​ | Trie insert & search]] 
-  * Implementați funcția numWordsWithSuffix care întoarce numărul de cuvinte din Trie având ca sufix cuvântul dat ca parametru+    - [[http://​www.geeksforgeeks.org/​trie-delete/​ | Trie delete]]
-</hidden>+
  
 +===== Bibliografie extra =====
  
 +    - [[https://​leetcode.com/​problems/​implement-trie-prefix-tree/​description/​ | Prefix tree]]
 +    - [[https://​www.hackerrank.com/​domains/​data-structures/​trie | Trie (hackerrank)]]
 +    - [[https://​leetcode.com/​tag/​trie/​ | Trie (leetcode)]]
sd-ca/laboratoare/lab-11.1589410880.txt.gz · Last modified: 2020/05/14 02:01 by teodor_stefan.dutu
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