Sortarea prin interschimbare BubbleSort 

 

Informaţii generale: 

       Metoda de sortare BubbleSort porneşte de la o proprietate evidentă a unui şir sortat: oricare două elemente alăturate respectă relaţia de ordine. Astfel, dacă oricare pereche de elemente alăturate respectă relaţia de ordine, atunci, conform tranzitivităţii relaţiei, întreg şirul va fi ordonat. Cele două elemente consecutive ale şirului de sortat vor forma “bulele” pe care se va verifica relaţia de ordine cerută. Este cea mai simplă metodă de sortare şi nu necesită cunoaşterea detaliată a limbajului de programare.

 

Prezentarea algoritmului:

            Se parcurge vectorul de sortat şi se compară elementele consecutive. Dacă acestea nu se află în ordinea dorită, se interschimbă. Când se va ajunge la ultimul element al vectorului, parcurgerea se reia şi se vor verifica din nou elementele vecine, cu realizarea interschimbărilor acolo unde sunt necesare,  până când, la o ultimă parcurgere nu mai este necesară nici o interschimbare, prin urmare, vectorul este ordonat.

            Se va folosi o variabilă de tip logic, care va marca dacă la o parcurgere se fac interschimbări (se iniţializează la începutul parcurgerii, iar dacă se face măcar o interschimbare, i se va schimba valoarea). Algoritmul se opreşte atunci când această variabilă îşi păstrează valoarea primită la începutul parcurgerii (nu au mai fost necesare interschimbări).

 

Exemplu :  şirul iniţial este {5, 8, 4, 7, 6}

i

x[1]

x[2]

x[3]

x[4]

x[5]

x[1],x[2]

5

8

4

7

6

Compar 5 cu 8: ordinea e cea dorită

x[2],x[3]

5

8

4

7

6

Compar 8 cu 4: ordinea nu e cea dorită ; se interschimbă

x[3],x[4]

5

4

8

7

6

Compar 8 cu 7: ordinea nu e cea dorită ; se interschimbă

x[4],x[5]

5

4

7

8

6

Compar 8 cu 6: ordinea nu e cea dorită ; se interschimbă ; se reia parcurgerea

x[1],x[2]

5

4

7

6

8

Compar 5 cu 4: ordinea nu e cea dorită ; se interschimbă ;

x[2],x[3]

4

5

7

6

8

x[3],x[4]

4

5

7

6

8

x[4],x[5]

4

5

6

7

8

La următoarea parcurgere, nu se mai realizează interschimbări

 

Varianta pseudocod a  algoritmului:

 repetă

ok←fals;

pentru i←1, n-1 execută

                dacă x[i]>x[i+1] atunci

                          x[i]↔x[i+1];

                         ok←adevarat;

                sfârşit dacă;

sfârşit pentru;

până când ok=fals;

 

Observaţii :

 

  1. Ultima parcurgere a vectorului se face  fără interschimbări.
  2. După prima parcurgere, elementul maxim s-a deplasat către ultima poziţie, după a doua, maximul dintre primele n-1 elemente s-a deplasat către penultima poziţie, etc; deci, la fiecare nouă parcurgere ar fi suficient să mergem cu un pas mai puţin decât la parcurgerea anterioară. Se poate construi, astfel, un algoritm îmbunătăţit:

index←n;

repetă

ok←fals;

pentru i←1, index-1 execută

dacă x[i]>x[i+1] atunci

                                  x[i]↔x[i+1];

                                  ok←adevarat;

sfârşit dacă;

sfârşit pentru;

indexindex-1;

până când ok=fals;

             Numărul de comparaţii efectuate nu depinde de gradul de sortare al şirului iniţial, fiind în orice situaţie .

În schimb, numărul de interschimbări depinde de proprietăţile şirului iniţial, astfel:

-      în cazul cel mai favorabil (şir sortat crescător) sunt necesare 0 interschimbări;

-      în cazul cel mai defavorabil (şir sortat descrescător), se vor efectua  interschimbări, deci  atribuiri.

Aşadar, algoritmul prezentat mai sus aparţine clasei O(n2).

Implementare C++:

 do

{ok=0;

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

if (x[i]>x[i+1])

 {aux=x[i];

                           x[i]=x[i+1];

                           x[i+1]=aux;

                           ok=1;

 }

 }while(ok);

Implementare Pascal:

repeat

ok:=true;

for i:=1 to n do

if x[i]>x[i+1] then

          begin

          aux:=x[i];

          x[i]:=x[i+1];

          x[i+1]:=aux;

          ok:=false;

          end;

 until ok;

 Mergi la pagina METODE DE SORTARE

   Aplicatii

 

Aplicaţie1: Se citeşte un vector a cu n elemente numere întregi. 

Să se ordoneze crescător elementele vectorului folosind metoda bulelor.

Program C++:

 #include <iostream.h>

#include <conio.h>

int n,i, a[20];

void citire(){

cin>>n;

for(i=1; i<=n; i++) cin>>a[i];}

void afis(){

for(i=1; i<=n; i++) cout<<a[i]<<” ”;}

void bule (int a[20], int n){

int aux, gata;

do {

gata=1;

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

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

                        aux=a[i]; a[i]=a[i+1]; a[i+1]=aux;

                        gata=0;}

} while (!gata); }

void main() {

citire();

bule (a,n);

afis();

getch(); }

Program Pascal:

PROGRAM BubbleSort1;

TYPE vector= ARRAY[1..20] OF INTEGER;

VAR a:vector;

            i, n: INTEGER;

PROCEDURE citire;

BEGIN

READLN(n);

FOR i:= 1 TO n DO READLN(a[i]);

END;

PROCEDURE afis;

BEGIN

FOR i:= 1 TO n DO WRITELN(a[i], ’   ’);

END;

PROCEDURE bule (VAR a:vector; VAR n:INTEGER);

VAR aux:INTEGER; gata:BOOLEAN;

BEGIN

REPEAT

gata:=TRUE;

FOR i:= 1 TO n-1 DO

            IF a[i]>a[i+1] THEN

                        BEGIN

                        aux:=a[i]; a[i]:=a[i+1]; a[i+1]:=aux;

                        gata:=FALSE;

                        END;

UNTIL gata;

END;

BEGIN

citire;

bule(a.n);

afis;

END.

 

 

Aplicaţie2: Se citeşte un vector a cu n elemente numere naturale. 

Să se ordoneze descrescător elementele vectorului după valoarea inversatului fiecărui element.

Program C++:

#include <iostream.h>

#include <conio.h>

int n,i, a[20];

void intersch(int &x, int&y){

int aux=x; x=y; y=aux;}

int inversat (int n) {

int inv=0;

while (n) {

            inv=inv*10+n%10;

            n=n/10; }

return inv; }

void sortare (int a[20], int n){

int gata;

do {

gata=1;

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

            if (inversat(a[i])<inversat(a[i+1])){

                        intersch(a[i], a[i+1]);

                        gata=0;}

} while (!gata); }

void main() {

cin>>n;

for(i=1; i<=n; i++) cin>>a[i];

sortare (a,n);

for(i=1; i<=n; i++) cout<<a[i]<<” ”;

getch(); }

Program Pascal:

PROGRAM BubbleSort2;

TYPE vector= ARRAY[1..20] OF INTEGER;

VAR a:vector;

            i, n: INTEGER;

PROCEDURE intersch (VAR x,y:INTEGER);

VAR aux:INTEGER;

BEGIN

aux:=x; x:=y; y:=aux;

END;

FUNCTION inversat (n:INTEGER):INTEGER;

VAR inv:INTEGER;

BEGIN

inv:=0;

WHILE n<>0 DO

BEGIN

inv:=inv*10 +n mod 10;

n:=n div 10;

END;

inversat:=inv;

END;

PROCEDURE SORTARE (VAR a:vector; VAR n:INTEGER);

VAR gata:BOOLEAN;

BEGIN

REPEAT

gata:=TRUE;

FOR i:= 1 TO n-1 DO

            IF inversat(a[i])<inversat(a[i+1]) THEN

                        BEGIN

                        intersch(a[i], a[i+1])

                        gata:=FALSE;

                        END;

UNTIL gata;

END;

BEGIN

READLN(n);

FOR i:= 1 TO n DO READLN(a[i]);

sortare(a.n);

FOR i:= 1 TO n DO WRITELN(a[i], ’   ’);

END.

 

Aplicaţie3: Din fişierul text clasa.in se citesc următoarele informaţii despre fiecare elev din clasă: numele, prenumele, media. Să se afişeze elevii din clasă ordonaţi descrescător după medie.

Program C++:

#include <iostream.h>

#include <conio.h>

#include

ifstream f(”clasa.in”);

struct elev {

char nume[20], prenume[20];

double media} c[30];

void main() {

int i, n;

f>>n;

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

f>>c[i].nume>>c[i].prenume>>c[i].media;

int gata;

do {gata=1;

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

            if (c[i].media<c[i+1].media) {

                        elev aux=c[i];c[i]=c[i+1];

                        c[i+1]=aux; gata=0;}

} while (!gata);          

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

cout<<c[i].nume<<” ”<<c[i].prenume<<” ”c[i].media<<endl;

f.close();

getch(); }

Program Pascal:

PROGRAM BubbleSort3;

TYPE elev=RECORD

                        nume, prenume: STRING[20]

media:REAL; END;

vector= ARRAY[1..30] OF elev;

VAR c:vector; aux:elev; gata:BOOLEAN;

            i, n: INTEGER; f:TEXT;

BEGIN

ASSIGN( f, ’clasa.in’);

RESET(f);

READLN(f,n);

FOR i :=1 TO n DO

READ (f, c[i]. nume, c[i].prenume, c[i].media);

REPEAT

gata:=true;

FOR i:= 1 TO n-1DO

IF c[i].media<c[i+1].media THEN

BEGIN

aux:=c[i];c[i]:=c[i+1];

                        c[i+1]:=aux;gata:=FALSE;

                        END;

UNTIL gata;

FOR i:=1 TO n DO

WRITELN(c[i]. nume, ’  ’, c[i].prenume, ’  ’c[i].media) ;

CLOSE(f);

END.

 

Aplicaţie4: Se consideră o listă liniară simplu înlănţuită. Scrieţi o funcţie care să ordoneze crescător nodurile din listă. Funcţia va primi ca parametru adresa primului nod al listei.

Observaţie:

Vom folosi o structură numită nod de forma:

-info de tip întreg;

-urm de tip pointer către un nod.

Funcţie C++:

void bubblesortasc (nod *prim) {

int gata; nod *p;

do {

gata=1;

for (p=prim;p->urm;p=p->urm )

//parcurg lista, începând cu primul nod

if (p->info > p->urm->info) {

            int aux=p->info;

p->info=p->urm->info;

p->urm->info=aux;

gata=0;}

while (!gata); }

Funcţie Pascal:

PROCEDURE bubblesortasc(prim: adresa);

VAR p:adresa; gata:BOOLEAN; aux:INTEGER;

BEGIN

REPEAT

gata:=TRUE;

p:=prim;

WHILE p^.urm<>NIL DO

            BEGIN

            IF p^.info> p^.urm^.info THEN

            BEGIN

            aux:=p^. info; p^. info:= p^.urm^.info;

            p^.urm^.info:=aux; gata:=FALSE;

            END;

UNTIL gata;

END;

 

 

 

Mergi la pagina METODE DE SORTARE