Differences

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

Link to this comparison view

sda-aa:laboratoare:07 [2021/04/12 06:42]
cristian.rusu
sda-aa:laboratoare:07 [2021/04/12 06:55] (current)
cristian.rusu [4. Exerciții]
Line 26: Line 26:
    * Este recomandat ca funcţia de indexare să existe explicit (să fie definită ca subprogram) atunci când are o formă complicată. Dacă are o formă simplă (cum ar fi o singură operaţie), această parte poate fi omisă.    * Este recomandat ca funcţia de indexare să existe explicit (să fie definită ca subprogram) atunci când are o formă complicată. Dacă are o formă simplă (cum ar fi o singură operaţie), această parte poate fi omisă.
  
-===== 2.3 Operații pe biți =====+=== 2.3 Operații pe biți ===
  
 Menţionăm următoarele operaţii pe biţi ce se pot folosi în C/C++ : Menţionăm următoarele operaţii pe biţi ce se pot folosi în C/C++ :
Line 47: Line 47:
    * n >> p == n / k    * n >> p == n / k
    * n & (k - 1) == n % k    * n & (k - 1) == n % k
-   ​* ​+
 Apar diferenţe în cazul numerelor negative.</​note>​ Apar diferenţe în cazul numerelor negative.</​note>​
  
  
-=== 3. Algoritmii de sortare ===+==== 3. Algoritmii de sortare ​====
  
-== 3.1 Heap Sort ==+=== 3.1 Heap Sort ===
    * Timp mediu: O(N log N)    * Timp mediu: O(N log N)
    * Timp la limită: O(N log N)    * Timp la limită: O(N log N)
Line 120: Line 120:
 } }
 </​code>​ </​code>​
 +
 +
 +=== 3.2 Radix Sort ===
 +
 +   * Timp mediu: O(N * k)
 +   * Timp la limită: O(N * k)
 +   * Memorie: O(N + k)
 +   * Stabil: DA
 +k = lungimea cuvântului/​cheii (word size)
 +
 +Vom prezenta varianta LSD (Least Signifiant Digit) a algoritmului de sortare.
 +
 +Descriere:
 +LSD Radix Sort este una dintre cele mai rapide metode de sortare.Aceasta se bazează pe sortarea în funcţie de cea mai nesemnificativă „cifră“.
 +   * Radix Sort nu are la bază o tehnică de comparare. Fiecare element din vector (sau atribut al unui element, în cazul structurilor) după care facem sortarea va fi numit cheie.
 +   * Cheile sunt gândite ca şiruri de „caractere“ (unde un „caracter“ poate fi un bit, o cifra, o literă, …).
 +
 +Algoritmul trece prin următorii paşi:
 +   * pornind de la poziţia celui mai nesemnificativ „caracter“,​ numără de câte ori apare fiecare „caracter“ pe poziţia respectivă,​ apoi împarte un vector auxiliar în secţiuni (imaginare). Numărul de secţiuni este numărul de „caractere“ diferite ce pot exista în vector, adică fiecărei secţiuni îi este asociat un „caracter“,​ dimensiunea unei secţiuni depinde de numărul de apariţii ale „caracterului“ asociat;
 +   * pune fiecare element (în vectorul auxiliar) în secţiunea corespunzătoare,​ apoi copiază vectorul auxiliar înapoi în vectorul ce trebuie sortat. Se obţine un vector sortat până la poziţia curentă;
 +   * trece la poziţia următoare şi repetă paşii, ultima poziţie fiind cea a celui mai semnificativ „caracter“.
 +
 +Implementare:​
 +Exemplul prezentat foloseşte un octet pe post de „caracter“. Putem interpreta acest exemplu şi ca scriere a numerelor în baza 256, valoarea fiecărui octet fiind o „cifră“.
 +
 +<code C>
 +#define BYTE 8
 +#define COUNT_BYTE 256
 +int obtineOctetul(int n,int byteNr)
 +{   //​cautam octetul de la pozitia byteNr
 +    //octetul de pe pozitia 0 este LSD = octetul cel mai din dreapta(pentru int)
 +    int bitsNr =  BYTE * byteNr;
 +    int mask = COUNT_BYTE - 1;
 +    return (n >> bitsNr) & mask;
 +}
 +void rad(int *a,int *b, int byteNr,int n)
 +{   //​sortare dupa octetul de pe pozitia byteNr,
 +    // pe pozitia 0 este LSD = octetul cel mai din dreapta
 +    int i,
 +        count[COUNT_BYTE] = {0}, //numaram cate elemente au "​car."​ i pe pozitia byteNr
 +        index[COUNT_BYTE] = {0}; //pozitia la care vom pune urmatorul element cu "​car."​ i
 +    for(i = 0; i < n;i++) {
 +        int car = obtineOctetul(a[i],​byteNr);​
 +        count[car]++;​
 +    }
 +    for(i = 1;i < COUNT_BYTE;​i++) //sectionam vectorul b
 +        index[i] = index[i-1] + count[i-1];
 +    for(i = 0; i < n; i++) { //umplem sectiunile
 +        int car = obtineOctetul(a[i],​byteNr);​
 +        b[index[car]++] = a[i];
 +    }
 +}
 +void radixSort(int *a,int n)
 +{
 +    int *b = new int[n], //vector folosit la copiere
 +        byteNr, //pozitia curenta
 +        k = sizeof(a[0]);​ //numarul de "​caractere"​
 +    for(byteNr = 0; byteNr < k; byteNr += 2) {
 +        rad(a, b, byteNr, n); //in loc sa copiem b inapoi in a la fiecare pas
 +        rad(b, a, byteNr + 1, n); //copiem doar o data la 2 pasi
 +    }
 +    delete []b;
 +}
 +</​code>​
 +
 +
 +<note important>​Exemplul prezentat funcţionează bine pentru întregi cu acelaşi semn.</​note>​
 +
 +<note important>​Performanţa de timp poate fi influenţată prin schimbarea lungimii cuvântului (k), adică prin schimbarea „bazei“ folosite.</​note>​
  
 ==== 4. Exerciții ==== ==== 4. Exerciții ====
  
-  - Se dă un vector cu n întregi (citit din fișierul input.txt, câte un număr pe fiecare linie)Scrieţi o funcţie care să creeze un arbore binar de căutare cu valorile din vectorScrieţi o funcţie care verifică dacă arborele este binar de căutare. Scrieţi o funcţie care verifică dacă o valoare (generată aleator) 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). [80nota+  - Generaţi ​un vector ​de n întregi ​cu n = 1e6Sortaţi vectorul cu cei doi algoritmi şi comparaţi rezultatele (aici ne intereseaza viteza sortării, vezi https://​stackoverflow.com/​questions/​5248915/​execution-time-of-c-program)[80% notă] 
-  - Acelașenunț ca ex. 1 dar acum păstrațarborele echilibrat ​(AVL). [20nota]+  - Introduceţi o variabilă globală cu care să contorizaţi numărul de apelări ale funcţiei „cerne“Afişnumărul de apelări necesare pentru construirea heap-ului (makeHeap) şi numărul de apelări necesare pentru tot algoritmul (heapSort). [10notă
 +  - Cu Radix Sort, încercaţsă sortaţun vector cu orice numere întregi ​(pozitive şi negative). Verificaţi rezultatul şi adăugaţi un pas în algoritm pentru a aşeza corect elementele. [10notă] 
 ==== 5. Probleme opționale, de interviu ==== ==== 5. Probleme opționale, 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 şi legăturile copil-părinte din P. +  - Se dă un vector ​cu n întregi, unde toate valorile din vector sunt cuprinse între 0 şi n^2 1Sortaţvectorul ​în timp O(n). Hint: încercaţsă folosiţaltă „bază“ decât 256 pentru algoritm.
-  - Propunețsoluții eficiente pentru a programa un program de tip "​auto-complete"​ pentru o listă de cuvinte (în timp ce tastați se afișează cele mai probabile 3 cuvinte la care vă referiți). Hint: verificați/căutațtrie sau arbori de prefixe.+
sda-aa/laboratoare/07.1618198936.txt.gz · Last modified: 2021/04/12 06:42 by cristian.rusu
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