Documente Academic
Documente Profesional
Documente Cultură
Eficența algoritmilor în
informatică
1
2
II .Argument
Am ales această temă pentru realizarea lucări de atestat deoarece este esențială în programare ,deci
indirect pentru un viitor în domeniul informatici.Acest proiect mă ajută la aprofundarea materiei de
bacalaureat și admitere la facultate deoarece doresc să urmăresc in această lucrare importanța eficenței
algoritmilor in rezolvarea problemelor. Într-un peisaj informatic în continuă schimbare, unde viteza și
eficiența sunt cheia succesului, capacitatea de a selecta și implementa algoritmi eficienți devine
crucială.
3
III. Introducere
Un algoritm reprezintă o secvență logică și bine definită de pași sau instrucțiuni care descriu modul de
rezolvare a unei probleme sau de realizare a unei sarcini specifice. Un algoritm trebuie să fie precis și
să conducă la obținerea unei soluții într-un număr finit de pași, fiind o metodă sistematică de abordare a
unei probleme. Principalele caracteristici ale unui algoritm includ:
1. Claritate: Un algoritm trebuie să fie formulat într-un mod clar și ușor de înțeles, astfel încât să
poată fi implementat și urmărit cu precizie.
2. Precizie:Instrucțiunile unui algoritm trebuie să fie definite în mod precis, eliminând orice
ambiguitate sau interpretare ambiguă.
3. Determinism: Un algoritm trebuie să fie deterministic, ceea ce înseamnă că, pornind de la
aceeași stare inițială și aceleași intrări, va produce întotdeauna aceeași ieșire.
4. Finitudine: Un algoritm trebuie să se termine într-un număr finit de pași. Nu trebuie să intre
într-un ciclu infinit sau să nu se oprească niciodată.
5. Eficență: Un algoritmul eficient utilizează resursele (cum ar fi timpul și spațiul de memorie)
într-un mod optim.
Pe măsură ce cerințele pentru manipularea datelor și rezolvarea problemelor devin din ce în ce mai
complexe, importanța algoritmilor eficienți devine din ce în ce mai evidentă. Alegerea și
implementarea unor algoritmi bine optimizați pot face diferența între o aplicație rapidă și eficientă și
una care întâmpină dificultăți în gestionarea volumelor mari de date.Eficiența algoritmilor în
informatică este un aspect crucial și se referă la capacitatea unui algoritm de a rezolva o problemă într-
un mod rapid și cu resurse minime. Există mai mulți factori care contribuie la eficiența unui algoritm,
iar aceștia pot varia în funcție de contextul problemei pe care algoritmul încearcă să o rezolve:
1. Complexitate temporală
2. Complexitate spațială
3. Scalabilitatea
Complexitatea temporală și spațială sunt doi parametri critici în evaluarea eficienței unui algoritm.
Acești indicatori oferă o perspectivă clară asupra modului în care performanța algoritmului se schimbă
în funcție de dimensiunea datelor de intrare și pot fi exprimați utilizând notația Big O.
a) Complexitate Temporală
4
Complexitatea temporală măsoară modul în care timpul de execuție al algoritmului crește odată cu
dimensiunea datelor de intrare. Este esențială pentru a înțelege cât de eficient va funcționa un algoritm
pe măsură ce volumul de date crește.
Exemplu:
Un algoritm cu complexitate temporală O(n) va avea un timp de execuție proporțional cu
dimensiunea datelor de intrare.
Un algoritm cu complexitate O(n^2) va avea un timp de execuție care crește cu pătratul
dimensiunii datelor.
b) Complexitate Spațială
Exemplu:
Un algoritm cu complexitate spațială O(n) folosește o cantitate de memorie proporțională cu
dimensiunea datelor de intrare.
Un algoritm cu complexitate O(1) folosește o cantitate constantă de memorie indiferent de
dimensiunea datelor.
Notația Big O este utilizată pentru a descrie comportamentul limită al algoritmilor în cel mai rău caz
(worst-case scenario). Aceasta furnizează o limită superioară a ratei de creștere a funcției de
complexitate în funcție de dimensiunea datelor de intrare.
Exemplu:
O(alg. log n) indică o creștere logaritmică.
O(n) indică o creștere liniară.
O(n^2) indică o creștere pătratică.
O(1) - Constantă: Operații care necesită un timp constant, indiferent de dimensiunea datelor.
O(log n) - Logaritmică: Exemplu: căutarea binară.
5
Reprezentarea grafica a complexitați algoritmilor(sursă: https://www.geeksforgeeks.org/what-is-
logarithmic-time-complexity/)
Testarea Scalabilității:
6
V.Studii de Caz: Analiza Eficienței Algoritmilor în
Diferite Contexte
Acest segment explorează studii de caz pentru a ilustra modul în care eficiența algoritmilor poate varia
în funcție de contextul specific al problemei. Studiile de caz acoperă diverse domenii, inclusiv sortare,
căutare și manipulare de date.
Sortarea eficientă este o componentă critică în prelucrarea și manipularea datelor. Vom compara
QuickSort și BubbleSort, două algoritme de sortare, sub aspectul eficienței în diverse scenarii.
a)QuickSort
QuickSort este un algoritm de sortare eficient și larg utilizat, care utilizează o strategie de împarte și
cucerește pentru a sorta elementele unei liste. A fost inventat de Tony Hoare în 1960 și este cunoscut
pentru eficiența sa în cazul mediu, având o complexitate de timp O(n log n). Iată cum funcționează
QuickSort:
Alegerea Pivotului: Se alege un element din listă, numit "pivot". Există diferite strategii pentru
alegerea pivotului, iar o alegere bună contribuie la performanța algoritmului.
Partiționare: Elementele mai mici decât pivotul sunt plasate în stânga acestuia, iar cele mai mari
în dreapta. Pivotul este acum în poziția corectă în lista sortată.
Sortarea Recursivă: Se aplică recursiv aceeași procedură asupra subliste create în stânga și în
dreapta pivotului.
Combinarea: Lista sortată este obținută prin combinarea rezultatelor sublistelor.
Caracteristici Cheie:
Eficiență în Cazul Mediu: O(n log n), unde n este numărul de elemente în listă.
Strategie de Partiționare Eficientă: QuickSort utilizează o strategie de partiționare care plasează
pivotul în poziția corectă, facilitând sortarea listelor mai mici.
QuickSort este un algoritm de sortare extrem de eficient și este frecvent utilizat în practică. Cu toate
acestea, în anumite situații specifice, cum ar fi atunci când se lucrează cu seturi de date aproape sortate,
este posibil să fie aleși algoritmi mai specializați.
7
b) BubbleSort
BubbleSort este un algoritm simplu de sortare care compară și interschimbă repetitiv elementele
adiacente într-o listă până când lista este sortată. Acest algoritm este numit astfel datorită modului în
care elementele mai mici "plutesc" la începutul listei, iar cele mai mari "bușesc" la sfârșit. Deși este un
algoritm ușor de înțeles, este mai puțin eficient decât algoritmi mai avansați, cum ar fi QuickSort sau
MergeSort.
Funcționare:
8
Caracteristici Cheie:
Complexitate în cazul mediu și cel mai rău: O(n^2), unde n este numărul de elemente în listă.
Adaptabilitate: este adaptabil la liste parțial sortate, deoarece se oprește dacă nu se fac
interschimbări într-o iterație completă.
Simplicitate: este ușor de implementat și de înțeles, făcându-l potrivit pentru scopuri
BubbleSort nu este un algoritm recomandat pentru liste mari sau aplicații în care performanța este
critică. În schimb, algoritmi mai avansați precum QuickSort sau MergeSort sunt preferați în astfel de
situații.
64 34 25 12 22 11 90
BubbleSort:
Pasul 1:
34 25 12 22 11 64 90
Pasul 2:
25 12 22 11 34 64 90
Pasul 3:
12 22 11 25 34 64 90
Pasul 4:
12 11 22 25 34 64 90
Pasul 5:
11 12 22 25 34 64 90
QuickSort:
9
Mai mici sau egali cu 34: 25, 12, 22, 11
Mai mari decât 34: 64, 90
1.Se dau înălțimile a n copii, numerotați de la 1 la n, exprimate prin numere naturale. Afișați numerele
de ordine ale copiilor în ordinea crescătoare a înălțimii lor.
(https://www.pbinfo.ro/probleme/618/inaltimi)
Intrare:
8 20 16 14 10 4 12
Ieșire:
6157432
10
#include <iostream>
int main()
cin>>n;
cin>>a[i];
b[i] = i+1;
while (ok){
ok=0;
if (a[i]>a[i+1])
swap(a[i], a[i+1]);
swap(b[i], b[i+1]);
ok=1;
11
}
cout<<b[i]<<" ";
return 0;
2. Se dă un vector cu n elemente, numere naturale. Afișați în ordine crescătoare valorile prime din acest
vector.
Exemplu:
Intrare
13 1 10 15 3 7 11
Ieșire
3 7 11 13
Rezolvare:
#include <iostream>
int main(){
int n, x[1005];
cin >> n;
12
for(int i = 0 ; i < n ; ++ i)
while(! sortat)
sortat = true;
x[i] = x[i+1];
x[i+1] = aux;
sortat = false;
for(int i = 0 ; i < n ; ++ i)
if(x[i] < 2)
prim = false;
prim = false;
if(x[i] % d == 0)
13
prim = false;
if(prim)
return 0;
Căutarea într-o listă este o operație fundamentală în informatică. Două metode comune de căutare sunt
Binary Search (căutarea binară) și Linear Search (căutarea liniară). Vom compara eficiența și
caracteristicile cheie ale acestor două metode.
Comparatie:
Fie vectorul:
14
1 2 3 4 5 6 7 8 9 10
Acesta este un exemplu de rulare a căutării binare pentru a găsi elementul 6 într-o listă sortată de
numere de la 1 la 10:
Pas cu pas, intervalul de căutare se micșorează până când se găsește elementul căutat. În acest exemplu,
6 este găsit la poziția 5 (indicele începe de la 0), ceea ce este afișat în rezultatul final.
15
Exemplu:
Intrare
1 2 5 6 9 10 14
8 14 9 14 16 15 4 2
Ieșire
01110001
Rezolvare
16
17
3. Manipularea Datelor: MergeSort vs. Insertion Sort
În manipularea datelor, alegerea algoritmilor de sortare poate avea un impact semnificativ asupra
eficienței operațiunilor. Vom compara două algoritme de sortare, MergeSort și Insertion Sort, în
contextul manipulării datelor.
a) MergeSort
Sortarea prin interclasare, sau Mergesort este o metodă eficientă de sortare a elementelor unui tablou,
bazată pe următoarea idee: dacă prima jumătate a tabloului are elementele sortate și a doua jumătate are
de asemenea elementele sortate, prin interclasare se va obține tabloul sortat.
Sortarea prin interclasare este un exemplu tipic de algoritm divide et impera: se sortează o secvență
delimitată de indicii st și dr:
dacă st <= dr, problema este elementară, secvența fiind deja sortată
dacă st < dr :
-se împarte problema în subprobleme, identificând mijlocul secvenței, m = (st + dr) / 2;
- se rezolvă subproblemele, sortând secvența delimitată de st și m, respectiv secvența
delimitată de m+1 și dr – apeluri recursive;
În secvența următoare tabloul tmp se consideră declarat global, de aceeași dimensiune ca v:
void MergeSort(int v[], int st, int dr)
{
if(st < dr)
{
int m = (st + dr) / 2;
MergeSort(v, st , m);
MergeSort(v, m + 1 , dr);
//Interclasare
int i = st, j = m + 1, k = 0;
while( i <= m && j <= dr )
if( v[i] < v[j])
tmp[++k] = v[i++];
else
tmp[++k] = v[j++];
while(i <= m)
tmp[++k] = v[i++];
while(j <= dr)
tmp[++k] = v[j++];
for(i = st , j = 1 ; i <= dr ; i ++ , j ++)
v[i] = tmp[j];
}
}
18
Observații:
complexitatea sortării prin interclasare este O(n⋅logn) ;
pentru interclasare este este necesar un spațiu de memorie suplimentar, de dimensiunea
tabloului care se sortează;
în secvența de mai sus tabloul tmp a fost declarat global; declararea sa locală poate duce
la depășirea stivei; o soluție pentru această situație poate fi alocarea dinamică a tabloului
auxiliar.
b) Insertion Sort
Insertion Sort este un algoritm simplu de sortare care construiește rezultatul final unul câte unul. Ideea
principală este de a lua fiecare element din șir și de a-l insera în locul potrivit în șirul deja sortat, până
când întregul șir este sortat. Acest algoritm este eficient pentru seturi mici de date, dar devine ineficient
pentru seturi mari.
#include <iostream>
#include <vector>
using namespace std;
void insertionSort(std::vector<int>& array) {
int n = array.size();
for (int i = 1; i < n; i++) {
int key = array[i];
int j = i - 1;
Vom analiza fiecare pas pentru sortarea vectorului (fig.1) folosind atât algoritmul MergeSort, cât și
Insertion Sort. Vom urmări vectorul pe măsură ce este sortat în fiecare pas.
12 11 13 5 6
(fig.1)
MergeSort:
19
1.
Divizăm vectorul în două jumătăți și aplicăm MergeSort recursiv pe fiecare jumătate
12 11 13
5 6
2.
Pentru 12 11 13
Divizăm în 12 11 13
3.
Pentru 12 11 este sortat ca 11 12
Insertion Sort:
1.
Inițial, vectorul este 12 11 13 5 6
3.
Elementul 13 este considerat sortat
4.
Se adaugă al patrulea element (5) în locul său corect astfel încât să obținem
5 11 12 13 6
20
5.
Se adaugă ultimul element (6) în locul său corect astfel încât să obținem vectorul sortat final
5 6 11 12 13
Acești pași descriu modul în care fiecare algoritm sortează vectorul dat. Merită să observăm că
MergeSort operează prin divizare și combinare, în timp ce Insertion Sort construiește șirul sortat un
element la un moment dat.
1. Timpul de Execuție:
Algoritmii diferă în termeni de timp necesar pentru a rezolva o anumită problemă. Algoritmi cu o
complexitate temporală mai mică vor rula mai rapid și vor asigura o performanță mai bună în cazul
unor seturi mari de date sau sarcini intensive.
2. Utilizarea Memoriei:
Complexitatea spațială a algoritmilor indică cantitatea de memorie pe care o utilizează. Algoritmii care
utilizează mai puțină memorie sunt mai eficienți în gestionarea resurselor și pot contribui la
performanța generală a sistemului, în special în medii cu resurse limitate.
3. Scalabilitate:
Un factor cheie în alegerea algoritmilor este capacitatea lor de a scala eficient odată cu creșterea
volumului de date sau utilizatorilor. Algoritmii scalabili vor menține o performanță bună în condiții de
creștere a încărcării sistemului.
21
Anumite algoritmi pot beneficia de resurse hardware specifice, precum unități de calcul grafic (GPU)
sau procesoare cu arhitectură specifică. Utilizarea acestor resurse poate îmbunătăți semnificativ
performanța.
7. Securitate:
În cazul algoritmilor de securitate, alegerea unui algoritm adecvat poate influența nivelul de securitate
al sistemului. Algoritmi criptografici eficienți și actualizați sunt esențiali pentru a asigura protecția
datelor.
9. Evoluția Tehnologică:
Pe măsură ce tehnologia evoluează, noi paradigme și algoritmi pot deveni disponibili. Adoptarea unor
algoritmi inovatori poate aduce beneficii semnificative în termeni de eficiență și performanță.
Așadar alegerea algoritmilor este un aspect esențial al dezvoltării software și are un impact direct
asupra performanței sistemelor informatice și aplicațiilor. Dezvoltatorii trebuie să evalueze cu atenție
caracteristicile și cerințele specifice ale fiecărui proiect pentru a face alegeri informate și pentru a
asigura performanța optimă a sistemului.
22
Un prim pas în direcția optimizării algoritmilor îl reprezintă analiza și profilarea atentă a codului
existent. Înțelegerea clară a timpului de execuție și a consumului de resurse este esențială pentru a
identifica zonele care necesită îmbunătățiri. Prin utilizarea instrumentelor de analiză și profilare,
dezvoltatorii pot identifica bottleneck-uri și pot localiza porțiuni ineficiente ale codului.
Un alt aspect important al optimizării constă în alegerea algoritmilor corespunzători la un nivel înalt.
Evaluarea și, dacă este posibil, schimbarea algoritmilor pentru variante mai eficiente sunt strategii
cheie în reducerea complexității temporale și spațiale. O alegere atentă a algoritmilor poate aduce
beneficii semnificative în termeni de performanță generală.
În ceea ce privește eficiența în utilizarea resurselor hardware, optimizarea pentru setul de instrucțiuni al
procesorului reprezintă o strategie crucială. Scrierea codului astfel încât să beneficieze la maximum de
setul specific de instrucțiuni al arhitecturii hardware contribuie la creșterea eficienței procesorului și la
accelerarea vitezei de execuție.
Alte tehnici de optimizare includ algoritmi paraleli și concurenți, care implică împărțirea sarcinilor în
bucăți mai mici și procesarea lor simultan pentru a profita de capacitatea de procesare paralelă.
Optimizarea pentru memoria continuă și adoptarea tehnologiilor noi reprezintă, de asemenea, elemente
esențiale în strategiile de optimizare. Structurarea datelor pentru a utiliza eficient memoria continuă și
adoptarea soluțiilor tehnologice actuale contribuie la îmbunătățirea accesului la date și la creșterea
generală a performanței.
Optimizarea algoritmilor este un proces complex, care necesită abordări multiple și adaptabilitate la
cerințele specifice ale fiecărui proiect. Prin aplicarea strategiilor și tehnicilor menționate, dezvoltatorii
pot obține performanțe superioare, contribuind astfel la eficiența și fiabilitatea sistemelor informatice și
a aplicațiilor.
23
VIII.Concluzie
De-a lungul dezvoltării software-ului, este important să se acorde o atenție deosebită selecției
algoritmilor potriviți pentru a asigura performanțe optime în diverse scenarii de utilizare. Întrucât
resursele, timpul și volumul datelor sunt adesea limitate, adoptarea algoritmilor eficienți devine o
prioritate în proiectarea și implementarea soluțiilor informatice. Astfel, o abordare atentă și bine
fundamentată a eficienței algoritmilor contribuie la creșterea performanței aplicațiilor, la economisirea
resurselor și la îmbunătățirea experienței utilizatorilor.
24