Table of Contents

Laboratorul 1: Algoritmi de sortare

1. Obiectivele laboratorului

2. Calculul complexitatii algoritmilor

A. Introducere

Analiza complexitatii unui algoritm are ca scop estimarea volumului de resurse de calcul necesare pentru executia algoritmului. Prin resurse se intelege:

Aceasta analiza este utila pentru a stabili daca un algoritm utilizeaza un volum acceptabil de resurse pentru rezolvarea unei probleme. In acest fel timpul de executie va fi exprimat prin numarul de operatii elementare executate. Sunt considerate operatii elementare cele aritmetice (adunare, scadere, inmultire, impartire), comparatiile si cele logice (negatie, conjuncte si disjunctie).

Este asadar suficient sa se contorizeze doar anumite tipuri de operatii elementare, numite operatii de baza. Timpul de executie al intregului algoritm se obtine insumand timpii de executie ai prelucrarilor componente.

Exemplul 1 - Suma a n numere

Consideram problema calculului sumei. Dimensiunea acestei probleme poate fi considerata n. Algoritmul si tabelul cu costurile corespunzatoare prelucrarilor sunt prezentate in Tabel. Insumand timpii de executie ai prelucrarilor elementare se obtine: $T(n)=n(c_3 + c_4 + c_5) + c_1 + c_2 + c_3$ deci $T(n)=k_1n + k_2$, adica timpul de executie depinde liniar de dimensiunea problemei. Costurile operatiilor elementare influenteaza doar constantele ce intervin in functia $T(n)$.

Exemplul 2 - inmultirea a 2 matrici

Consideram problema determinarii produsului a doua matrici: A de dimensiune $m \times n$ si B de dimensiune $n \times p$. In acest caz dimensiunea problemei este determinata de trei valori: $(m, n, p)$.

In practica nu este necesara o analiza atat de detaliata ci este suficient sa se identifice operatia dominanta si sa se estimeze numarul de repetari ale acesteia. Prin operatie dominanta se intelege operatia care contribuie cel mai mult la timpul de executie a algoritmului si de regula este operatia ce apare in ciclul cel mai interior. in exemplul ar putea fi considerata ca operatie dominanta, operatia de inmultire. In acest caz costul executiei algoritmului ar fi $T(m, n, p)=mnp$.

B. Caracterizarea unui algoritm

Numim sortare orice asezare(sau - mai clar - reasezare) a unor elemente date in asa fel incat, dupa asezare, sa existe o ordine completa in functie de un atribut(numit cheie) al elementelor.

Pentru a exista o ordine completa, trebuie sa alegem o relatie pe care vrem sa o impunem. Daca relatia este valabila intre oricare doua elemente pentru care primul element este asezat la stanga celui de-al doilea, atunci avem o ordine completa.

Exemplu: daca alegem drept cheie un atribut numar intreg si relatia mai mic sau egal, obtinem ordinea crescatoare.

Vom descrie un algoritm de sortare prin:

Folosim notatia O(n) pentru a indica:

3. Implementarea unor algoritmi de sortare

In acest curs ati vazut deja algoritmi de sortare precum

A. Bubble sort

Caracteristici:

Descriere: Sortarea prin metoda bulelor se considera drept una din cele mai putin efective metode de sortare, dar cu un algoritm mai simplu.

Ideea de baza a sortarii prin metoda bulelor este in a parcurge tabloul, de la stanga spre dreapta, fiind comparate elementele alaturate a[i] si a[i+1]. Daca vor fi gasite 2 elemente neordonate, valorile lor vor fi interschimbate. Parcurgerea tabloului de la stanga spre dreapta se va repeta atat timp cat vor fi intalnite elemente neordonate.

Implementarea:

//sortare descrescatoare
void bubble(int a[],int n)
{
    int i,schimbat,aux;
    do {
        schimbat = 0;
        // parcurgem vectorul
        for(i = 0; i < n-1; i++) {
	    // daca valoarea i din vectorul a este mai mica decat cea de pe pozitia i+1
            if (a[i] < a[i+1]) { 
                // interschimbare
	        aux = a[i];
		a[i] = a[i+1];
		a[i+1] = aux;
		schimbat = 1;
	    }
        }
    } while(schimbat);
}

B. Selection sort

Caracteristici:

Descriere: Acest algoritm selecteaza, la fiecare pas i, cel mai mic element din vectorul nesortat(de la pozitia i pana la n). Valoarea minima gasita la pasul i este pusa in vector la pozitia i, facandu-se intereschimbarea cu pozitia actuala a minimului. Nu este un algoritm indicat pentru vectorii mari, in majoritatea cazurilor oferind rezultate mai slabe decat insertion sort si bubble sort.

Implementarea:

void selectionSort(int a[],int n)
{
	int i,j,aux,min,minPoz;
	for(i = 0; i < n - 1;i++)
	{
		minPoz = i;
		min = a[i];
		for(j = i + 1;j < n;j++) //selectam minimul
		//din vectorul ramas( de la i+1 la n)
		{
			if(min > a[j]) //sortare crescatoare
			{
				minPoz = j; //pozitia elementului minim
				min = a[j];
			}
		}
		aux = a[i] ;
		a[i] = a[minPoz]; //interschimbare
		a[minPoz] = aux;
	}
}

C. Insertion sort

Caracteristici:

Descriere: Spre deosebire de alti algoritmi de sortare, sortarea prin insertie este folosita destul de des pentru sortarea tablourilor cu numar mic de elemente. De exemplu, poate fi folosit pentru a imbunatati rutina de sortare rapida.

Implementarea:

void insertionSort(int a[], int n)
{
    int i, j, aux;
    for (i = 1; i < n; i++)
    {
        j = i;
        while (j > 0 && a[j - 1] > a[j])
        { //cautam pozitia pe care sa mutam a[i]
            aux = a[j]; //interschimbare
            a[j] = a[j - 1];
            a[--j] = aux;
        }
    }
}

D. Merge sort

Caracteristici:

Descriere: in cazul sortarii prin interclasare, vectorii care se interclaseaza sunt doua secvente ordonate din acelasi vector. Sortarea prin interclasare utilizeaza metoda Divide et Impera:

corespunzatoare(cu 2 elemente). Cele doua secvente vor alcatui un subsir ordonat din vector mai mare(cu 4 elemente) care, la randul lui, se va interclasa cu un subsir corespunzator(cu 4 elemente) s.a.m.d.

E. Quick sort

Caracteristici:

Descriere: Quick Sort este unul dintre cei mai rapizi si mai utilizati algoritmi de sortare pana in acest moment,bazandu-se pe tehnica „Divide et impera“. Desi cazul cel mai nefavorabil este O(N^2), in practica, QuickSort ofera rezultate mai bune decat restul algoritmilor de sortare din clasa „O(N log N)“.

Algoritmul se bazeaza pe urmatorii pasi:

4. Exercitii

  1. Alegeti un algoritm A (dintre Bubble, Insertion si Selection) si un algoritm B (dintre Merge si Quick). Introduceti niste variabile globale cu care sa contorizati numarul de comparatii pentru algoritmii A si B. Comparati rezultatele pentru un vector de intregi de lungime n = 20.
  2. Implementati un algoritm (dintre Bubble, Insertion si Selection) pentru sortarea unui vector cu n cuvinte de maxim 4 litere fiecare.
  3. Implementati un algoritm (dintre Merge si Quick) pentru sortarea unui vector de structuri, unde fiecare structura reprezinta un moment de timp(int ora, min, sec).
  4. Se da un vector de n intregi, iar toate valorile din vector sunt intre 0 si 1000. Sortati vectorul in timp O(n).

Nota: Implementati toti algoritmii in fisiere separate (.c si .h) si apoi apelati-le din main.c