6.7 Metode de sortare(naive)

Sortarea prin interschimbare(Bubble Sort)
Ideea de baza a metodei este de a traversa tabloul şi a compara fiecare element cu succesorul său. Dacă nu sunt în ordinea dorita, cele două elemente se interschimbă între ele. Tabloul este traversat in mod repetat până când, la o parcurgere completă, nu se mai execută nici o interschimbare între elemente, fapt echivalent cu presupunerea că tabloul este sortat. Presupunand ca se doreste sortarea crescatoare a elementelor, putem observa ca valorile cele mai mare au tendinta de “a migra” catre capatul din dreapta, precum bulele de aer in apa. Exemplu:

Prima traversare:

( 5 1 4 2 8 ) –> ( 1 5 4 2 8 ),  primele doua elemente nu respecta relatia de ordine dorita(v[i]>v[i+1]) si sunt interschimbate.

( 1 5 4 2 8 ) –>  ( 1 4 5 2 8 ), interschimba 5 cu 4

( 1 4 5 2 8 ) –>  ( 1 4 2 5 8 ), interschimba 5 cu 2

Ajunge la capatul sirului si reia, deoarece pe parcursul traversarii au fost realizate interschimbari

A doua traversare:

( 1 4 2 5 8 ) –> ( 1 2 4 5 8 ), interschimba 4 cu 2

Ajunge la capatul sirului si reia, deoarece pe parcursul traversarii au fost realizate interschimbari

A treia traversare:

In aceasta traversare nu se mai efectueaza interschimbari, deci elementele sunt asezate in ordinea dorita si algoritmul se incheie.

In cea mai elementara forma, algoritmul poate fi redat dupa cum urmeaza: citeste n

pentru i=1, n, 1, executa

citeste v[i]

pentru i=1, n-1, 1 executa

pentru j=1, n-1, 1 executa

daca v[j]>v[j+1] atunci

          aux=v[j];

          v[j]=v[j+1];

          v[j+1]=aux

sfarsit daca

sfarsit pentru

sfarsit pentru Observam ca, indiferent de asezarea initiala a valorilor in vector, algoritmul realizeaza n2 operatii. Se pune astfel, problema optimizarii sale, o varianta foarte accesibila fiind aceea de a opri traversarea vectorului in momentul in care nu se mai inregistreaza interschimbari, #include 

using namespace std;

int main

{

int v[10], i, n, invers, aux;

cout<<"n="; cin>>n;

for(i=1;i<=n;i++){

cout<<"v["<>v[i];}

do {

invers=1;

for(i=1;i<=n-1;i++)

if(v[i]>v[i+1]){

    aux=v[i];

    v[i]=v[i+1];

    v[i+1]=aux;

    invers=0;}

}

while(invers);

for(i=1;i<=n;i++)  cout<<v[i]<<" ";

return 0; } In aceasta varianta, daca valorile sunt in ordinea dorita de la inceput, complexitatea este O(n).

Sortarea prin selectie
"Ideea de baza a acestei metode este de a determina repetititv valoarea minima si de a o plasa la inceput. Mai precis, in pasul 1, se determina valoarea subsirului v1, " v2,…, vn si se plaseaza pe pozitia 1. In pasul 2, se determina valoarea subsirului v2, v3…, vn si se plaseaza pe pozitia 2. Algoritmul, evident, va rula n-1 pasi. Observam ca, in urma fiecarei traversari a vectorului, acesta va fi impartit, practic, in doua. Subsirul v1, v2,… vi va fi sortat crescator, subisrul vi+1, vi+2, …vn va fi nesortat. Exemplul urmator reda aplicarea acestui algoritm, considerand ca vectorul v contine valorile: 5 1 4 2 8. 5 1 4 2 8   -> 1 5 4 2 8 determina minul in pozitia a 2-a si il va muta pe pozitia 1

1 5 4 2 8  -> 1 2 4 5 8 determina minimul pe pozitia a 4-a si il va muta pe pozitia a 2-a

1 2 4 5 8 -> 1 2 4 5 8 determina minimul pe pozitia a 3-a si il va muta pe pozitia a 3-a (practic nu se modifica starea vectorului)

1 2 4 5 8 -> 1 2 4 5 8 determina minimul pe pozitia a 4-a si il va muta pe pozitia a 4-a (practic nu se modifica starea vectorului)

Algoritmul se opreste dupa n-1 pasi, unde n este numarul elementelor din vector.

In pseudocod algoritmul poate fi redat dupa cum urmeaza: citeste n

pentru i=1, n, 1, executa

    citeste v[i]

pentru i=1, n-1, 1 executa

          min=v[i]

          pozmin=i

pentru j=i+1, n, 1 executa

        daca v[j]< min atunci

                    min=v[j]

                    pozmin=j

       sfarsit daca

sfarsit pentru

aux=v[i]

v[i]=min

v[pozmin]=aux

sfarsit pentru Complexitatea acestui algoritm este O(n2). Implementarea lui poate fi lasata ca exercitiu.

Sortarea prin insertie
Acest algoritm urmareste inserarea, pe rand, a fiecarui element al vectorului in pozitia in care toate elementele aflate la stanga sunt mai mici decat el. Sa luam spre exemplu sirul 5 1 4 2 8. Vom incepe cu cel de-al doilea element, primul fiind, in momentul initial, mai mare decat toate elementele aflate in stanga lui. Cum valoarea celui de-al doilea element este 1, il vom insera in vector inaintea valorii 5 5 1 4 2 8   ->  1 5 4 2 8

Luand in considerare al treilea element, 4, observam ca trebuie sa-l introducem inaintea valorii 5

1 5 4 2 8   -> 1 4 5 2 8

Urmatorul element este 2, iar el va fi inserat inaintea lui 4

1 4 5 2 8   -> 1 2 4 5 8

Ultima valoare din sir, 8, este lasata pe loc, fiind mai mare decat toate elementele precedente

1 2 4 5 8  -> 1 2 4 5 8

Observam ca, la fiecare pas, algoritmul creaza doua subsiruri in sirul initial. Cel aflat la stanga elementului curent, care este sortat si cel aflat la dreapta, cu elemente asezate in ordinea initiala. Complexitatea algoritmului este O(n2), cazul cel mai nefavorabil fiind acela in care elementele sirului sunt in ordine descrescatoare. citeste n

pentru i=1, n, 1, executa

          citeste v[i]

pentru i=2, n,1 executa

     aux = a[i]

     j := i-1;

cat timp (j>=1) si (a[j]>aux) 

a[j+1] := a[j];

j := j-1;

sfarsit cat timp                                             

a[j+1] := aux;

sfarsit pentru;

Redam, mai jos, o modalitate de implementare a algoritmului. #include 

using namespace std;

int v[10],i,j,n,aux;

int main{

cout<<"n=";

cin>>n;

for(i=1;i<=n;i++){

cout<<"v["<>v[i]; }

for(i=2;i<=n;i++){

aux = v[i];

j= i-1;

while((j>=1)&& (v[j]>aux)){

v[j+1]= v[j];

j= j-1;}

v[j+1]= aux;

}

for(i=1;i<=n;i++) cout<<v[i]<<" ";

return 0;

}