Differences

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

Link to this comparison view

sda-ab:laboratoare:07 [2021/03/06 21:30]
leonard.necula
sda-ab:laboratoare:07 [2021/04/04 14:45] (current)
leonard.necula [1. Obiectivele laboratorului]
Line 1: Line 1:
 ===== Laboratorul 6: BST si AVL ===== ===== Laboratorul 6: BST si AVL =====
 +
 +====== 1. Obiectivele laboratorului ======
 +
 +  *Intelegerea notiunii de arbore binar de cautare (BST)
 +  *Intelegerea notiunii de arbore binar de cautare echilibrat (AVL)
 +
 +
 +Structura laboratorului se gaseste in **[[https://​github.com/​sda-ab/​lab-06-tasks|acest link.]]**
 +
 +====== 2. BST (Binary Search Tree)  ======
 +
 +BST este un arbore binar cu o structură specială adaptată căutărilor eficiente, având următoarele proprietăți:​
 +  *se dă un nod rădăcină (numit si **root**)
 +  *în subarborele său stâng sunt stocate valori **mai mici** decât cea din rădăcină
 +  *în subarborele său drept sunt stocate valori **mai mari** decât cea din rădăcină
 +
 +<note warning>​Într-un BST **NU** apar valori duplicat, iar criteriul/​valoarea în funcție de care se face sortarea se mai numește și **cheie**(key).Cheile sunt alese în așa fel încât proprietatea BST sa se verifice la fiecare nivel.</​note>​
 +
 +**Operații specifice BST**
 +  *Inserarea/​Căutarea/​Ștergerea unui element
 +  *Găsirea predecesorului/​succesorului unui element
 +  *Afișarea datelor stocate in forma sortată
 +  *Găsirea elementului min/max/al k-lea ca valoare
 +
 +{{ :​sda-ab:​laboratoare:​binary-search-tree-example.png?​400 |}}
 +<​note>​Se poate observa că parcurgerea în **inordine(SRD)** a unui BST va furniza un șir de numere ordonat crescător.</​note>​
 +
 +=== 2.1. Inserarea unui element într-un BST ===
 +
 +Operația de inserarea a unui element într-un BST adaugă elementul ca frunza a arborelui, iar mai apoi nodul cu cheia data va fi inserat ca fiu stâng sau drept in așa fel încât sa se respecte proprietatea BST.
 +<code c>
 +Node* newNode(Data data)
 +{  Node* node = (Node*)malloc(sizeof(Node));​
 +    node->​val = data;
 +    node->​left = node->​right = NULL;
 +    return node;
 +}
 +
 +Node* insert(Node* node, int key)
 +{ // daca (sub)arborele e gol – se creeaza un nod 
 +   //si se returneaza adresa
 +    if (node == NULL) return newNode(key);​
 + 
 +    //altfel se coboara la stanga sau dreapta in arbore ​
 +    if (key < node->​val) ​ node->​left ​ = insert(node->​left,​ key);
 +                          else if (key > node->​val) ​
 +        ​  ​    ​node->​right = insert(node->​right,​ key);   
 +     //​pointerul node se intoarce nemodificat pe acest return ​
 +    return node;
 +} //nu se adauga elemente egale
 +</​code>​
 +
 +{{ :​sda-ab:​laboratoare:​binary-search-tree-insertion-animation.gif?​400 |}}
 +
 +=== 2.2. Căutarea unui element într-un BST ===
 +
 +  *se începe cu rădăcina, daca valoarea căutata este chiar rădăcina - return
 +  *daca valoarea cautata < cea stocata in rădăcină – se caută in subarborele stâng, altfel in cel drept. ​
 +  *cautarea are loc pana la gasirea elementului sau pana se ajunge la NULL.
 +<code c>
 +Node* search(Node* root, int key) {
 +    //daca radacina e null sau s-a gasit elementul
 +    if (root == NULL || root->​val == key)
 +      return root;
 +    //daca valoarea stocata in radacina e mai mica decat cheia
 +    if (root->​val < key)  return search(root->​right,​ key);
 +    // daca valoarea stocata in radacina e mai mare decat cheia
 +    return search(root->​left,​ key);
 +} //daca nu se gaseste nod cu aceasta cheie se returneaza NULL
 +
 +</​code>​
 +
 +=== 2.3. Ștergerea unui element într-un BST ===
 +
 +La partea de ștergere, trebuie avut în vedere:
 +  *Dacă nodul este **frunză** - se elibereaza spatiul ocupat si se seteaza legatura parintelui catre acel nod cu NULL
 +{{ :​sda-ab:​laboratoare:​stergere_bst_1.png?​400 |}}
 +  *Dacă nodul are doar un subarbore - nodul e scos din arbore și singurul sau copil (subarbore) e legat direct la parintele său (**OBS**- trebuie actualizat pointerul la stânga sau dreapta din parintele nodului de șters ca să pointeza catre subarborele nodului de șters)
 +{{ :​sda-ab:​laboratoare:​stergere_bst_2.png?​400 |}}
 +  *Dacă nodul are doi subarbori - se bazeaza pe ideea că același set de valori poate fi reprezentat folosind 2 BST diferiți în așa fel încât să ne reducem la unul dintre cele două cazuri de mai sus.
 +{{ :​sda-ab:​laboratoare:​stergere_bst_3_1.png?​400 |}}
 +<note tip>Idee : Se alege valoarea minimă din subarborele drept, se interschimbă cu valoarea rădăcinii,​ iar apoi se reface arborele pentru a păstra proprietatea BST</​note>​
 +{{ :​sda-ab:​laboratoare:​stergere_bst_3_3.png?​400 |}}
 +<note tip>​Pentru a șterge nodul cu valoarea 12, se caută valoarea minimă in subarborele drept(prin inordine(SRD)),​ se înlocuieste cu această valoarea,​iar apoi valoarea duplicat este ștearsă, ajungându-se la cazul II, în care nodul cu valoarea actualizată 19 are un singur subarbore.</​note>​
 +
 +====== 3. AVL (Adelson-Velsky and Landis tree)  ======
 +
 +Un **AVL** este un arbore binar de căutare echilibrat.(Proprietatea de echilibru trebuie respectata pentru fiecare nod - înălțimea
 +subarborelui stâng al nodului diferă de inaltimea subarborelui drept al nodului prin cel mult o unitate). De asemenea, trebuie păstrată si condiția de BST.
 +<​note>​
 +Arbore ​ binar **perfect** ​ - fiecare nod are exact 2 copii si  toate frunzele sunt la acelasi nivel.
 +
 +Arbore binar **complet** ​ -  un arbore binar care este complet umplut cu posibila exceptie a ultimului nivel care este umplut de la stanga la dreapta ​
 +
 +**OBS!** - arborii compleți sau perfecți sunt implicit echilibrați
 +
 +</​note>​
 +=== 3.1 Reprezentarea unui nod AVL ===
 +
 +<code c>
 +typedef int Data;    ​
 +typedef struct N  Node;  ​
 +
 + ​struct N { 
 +        int height; //inaltimea
 +        Data val; // datele efective memorate ​
 +        struct ​ N  *left,​*right;​ // legatura catre subarbori ​
 +};
 +
 +</​code>​
 +
 +**OBS** - înălțimea unui AVL este floor(log N), iar orice **cautare/​adaugare/​stergere/​gasire min/max de element** se va realiza cu complexitatea **O(log N)** - cost amortizat pe mai multe operații.
 +<note warning>​**Adăugarea/​Ștergerea** unui nod poate conduce la modificarea conditiei de echilibru, de aceea se folosesc tehnici de **rotație** pentru a reface proprietatea AVL</​note>​
 +
 +=== 3.2 Inserarea unui nod in AVL ===
 +
 +Operația constă în inserția unui nod într-un BST, urmată de reechilibrarea arborelui.
 +Există doua tipuri de rotații (care pastrează proprietatea BST):
 +  *rotație la dreapta
 +  *rotație la stânga
 +{{ :​sda-ab:​laboratoare:​tree_rotation.gif?​300 |}}
 +
 +=== 3.2.1 Rotații simple ===
 +
 +  ***RR** - x copilul drept al lui y, y copilul drept al lui z
 +{{ :​sda-ab:​laboratoare:​avl_rr.png?​300 |}}
 +  ***LL** - x este copilul stâng al lui y, y copilul stâng al lui z
 +{{ :​sda-ab:​laboratoare:​avl_ll.png?​300 |}}
 +
 +=== 3.2.1 Rotații duble ===
 +  ***LR** - y e copilul stang al lui z si x e copilul drept al lui y  - rotație la stanga + rotație la dreapta
 +{{ :​sda-ab:​laboratoare:​avl_lr.png?​400 |}}
 +  ***RL** - y e copilul drept al lui z si x e copilul stâng al lui y – rotașie dreapta +rotație stânga ​
 +{{ :​sda-ab:​laboratoare:​avl_rl.png?​400 |}}
 +
 +<​note>​**OBS** Ștergerea unui nod se bazeaza pe cea pentru BST, cu updatarea înălțimii și rebalansarea făcută exact ca in cazul inserării unui nod </​note>​
 +
 +
  
  
sda-ab/laboratoare/07.1615059001.txt.gz · Last modified: 2021/03/06 21:30 by leonard.necula
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