Sortarea prin metoda ShakerSort (CocktailSort) 

Informaţii generale:

        Această metodă de sortare este o îmbunătăţire a sortării prin metoda bulelor, prezentată anterior. În metoda bulelor, se repetă parcurgerea totală a şirului de sortat, atât timp cât sunt în vector elemente vecine, “bule”, care nu sunt în poziţia dorită. Acolo unde sunt identificate bule, elementele se interschimbă. Reluarea parcurgerii se opreşte când la ultima parcurgere nu se mai întâlnesc bule. Pentru a marca dacă într-o parcurgere mai sunt bule, se foloseşte o variabilă ce poate avea două stări.

 

Prezentarea algoritmului:

Pentru ordonare crescătoare, la metoda bulelor, se observă că la fiecare parcurgere, elementele mari se deplasează spre sfârşitul vectorului, astfel încât nu ar mai fi necesar să fie parcurse aceste elemente. Se foloseşte o variabilă nouă, dr,  care va memora indicele ultimei valori care a făcut parte dintr-o bulă, următoarea parcurgere realizându-se până la acel indice. Apoi, se va face o parcurgere de la dreapta la stânga, reţinându-se într-o altă variabilă poziţia inferioară, st,  din care va porni următoarea parcurgere, deoarece şi către început se deplasează în ordine elementele mici.

K.E. Inverson a făcut următoarea observaţie: dacă j este un indice astfel încât x[j] şi x[j+1] nu sunt interschimbate în două treceri consecutive, în direcţii opuse, atunci x[j] şi x[j+1] sunt în poziţiile lor finale, nefiind necesar să mai fie ulterior parcurse.

Deci, vectorul se parcurge în ambele sensuri, ducând prin fiecare parcurgere elementele mari, respectiv mici spre capete. Algoritmul se opreşte când cele două variabile, st şi dr, indică acelaşi element (se întâlnesc) sau la ultima parcurgere nu s-au mai făcut interschimbări (t=0).

Exemplu: Fie şirul 128, 77, 905, 403, 372, 478, 553, 348, 237, 878

 

 

i

1

2

3

4

5

6

7

8

9

10

x[i]

128

77

905

403

372

478

553

348

237

878

   st=1                                                                                  dr=10

i

1

2

3

4

5

6

7

8

9

10

x[i]

77

128

403

372

478

553

348

237

878

905

                          st=1                                                                         dr=9    

i

1

2

3

4

5

6

7

8

9

10

x[i]

77

128

237

403

372

478

553

348

878

905

→               st=4                                         dr=9 

i

1

2

3

4

5

6

7

8

9

10

x[i]

77

128

237

372

403

478

348

553

878

905 

   st=4                       dr=7                      

i

1

2

3

4

5

6

7

8

9

10

x[i]

77

128

237

348

372

403

478

553

878

905 

→                                      st=5              dr=7

i

1

2

3

4

5

6

7

8

9

10

x[i]

77

128

237

348

372

403

478

553

878

905

t=0                                                                             st=5              dr=7

 

 

Varianta pseudocod a  algoritmului:

st←1;

dr←n;

repetă

            t←0;

            pentru i = st, dr-1 execută

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

                                   interschimb (x[i], x[i+1]);

                                   t←i;

                        sfârşit dacă;

            sfârşit pentru;

            dacă t≠0 atunci

                        dr←t;

                        t←0;

                        pentru i=dr, st+1, -1 execută

                                   dacă x[i] <x[i-1] atunci

                                               interschimb( x[i], x[i-1])

                                               t←i;

                                   sfârşit dacă;

                        st←t;

            sfârşit dacă;

până când t=0 sau st=dr;

            Prin metoda ShakerSort se îmbunătăţeşte perfomanţa sortării cu bule. Prin treceri alternate în direcţii opuse, numărul mediu de comparaţii este uşor redus, însă algoritmul nu se îmbunătăţeşte în aşa fel încât să devină mai eficient nici faţă de inserţia directă, InsertSort. Algoritmul rămâne în categoria ordinul  O(n2).

 

Implementare C++:

void shaker ()

{ int i, st, dr, t, aux;

st=1;

dr=n;

do

            {t=0;

            for (i=st; i<=dr-1; i++)

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

                                   {aux=x[i];

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

                                   x[i+1]=aux;

                                   t=i; }

            if (t!=0)

                        {dr=t;

                        t=0;

  for (i=dr; i>=st+1; i--)

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

                                               {aux=x[i];

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

                                               x[i+1]=aux;

                                               t=i; }}

            st=t;}

}

while (t!=0 && st !=dr) ;

}

 

Implementare Pascal:

procedure shaker ;

var  i, st, dr, t, aux:integer;

begin

st:=1;

dr:=n;

repeat

            t:=0;

            for  i:=st to dr-1 do

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

                                   begin

aux:=x[i];

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

                                      x[i+1]:=aux;

                                      t:=i;

end

            if t<>0 then

                        begin

                             dr:=t;

                              t:=0;

for  i=dr downto st+1 do

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

                                     begin

aux=x[i];

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

                                             x[i+1]=aux;

                                             t=i;

end;

end;

            st:=t;

until (t=0) or (st =dr) ;

end;

 

  Mergi la pagina METODE DE SORTARE

Aplicaţii

 

Aplicaţie1: Să se scrie o funcţie de ordonare care primeşte 3 parametri: un vector x cu maxim 100 de elemente numere întregi, n reprezentând numărul de elemente şi numărul k mai mic decât n.Funcţia ordonează crescător primele k elemente şi descrescător celelalte n-k.

Program C++:

#include <iostream.h>

#include <conio.h>

int x[100], i, n, k;

void shakersort (int x[100], int n, int k){

int i, st, dr, t, aux;

st=1;dr=k;

do{t=0;

for (i=st; i<=dr-1; i++)

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

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

            x[i+1]=aux;t=i; }

            if (t!=0){dr=t;t=0;

for (i=dr; i>=st+1; i--)

            if (x[i]<x[i+1]){

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

                        x[i+1]=aux;t=i; }}

            st=t;}}

while (t!=0 && st !=dr) ;

st=k+1;dr=n;

do{t=0;

for (i=st; i<=dr-1; i++)

if (x[i]<x[i+1]){

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

                        x[i+1]=aux;t=i; }

            if (t!=0){dr=t;t=0;

for (i=dr; i>=st+1; i--)

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

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

                        x[i+1]=aux;t=i; }}

            st=t;}}

while (t!=0 && st !=dr) ;}

void main(){

cin>>n>>k;

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

shakersort(x, n, k);

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

Program Pascal :

PROGRAM ShakerSort1;

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

VAR x:vector; i,n,k:INTEGER;

PROCEDURE ShakerSort(VAR x:vector; n,k:INTEGER);

VAR  i, st, dr, t, aux:INTEGER;

BEGIN

st:=1;dr:=k;

REPEAT

t:=0;

FOR  i:=st TO dr-1 DO

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

            BEGIN

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

            x[i+1]:=aux;t:=i; END

IF t<>0 THEN

            BEGIN

            dr:=t;   t:=0;

FOR  i=dr DOWNTO st+1 DO

IF x[i]<x[i+1] THEN             BEGIN

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

x[i+1]=aux;t=i;END;

END;

            st:=t;

UNTIL (t=0) OR (st =dr) ;

st:=k+1;dr:=n;

REPEAT

t:=0;

FOR  i:=st TO dr-1 DO

IF x[i]<x[i+1] THEN

            BEGIN

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

            x[i+1]:=aux;t:=i; END

IF t<>0 THEN

            BEGIN

            dr:=t;   t:=0;

FOR  i=dr DOWNTO st+1 DO

IF x[i]>x[i+1] THEN             BEGIN

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

x[i+1]=aux;t=i;END;

END;

            st:=t;

UNTIL (t=0) OR (st =dr) ;

END;

BEGIN

READLN(n,k);

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

ShakerSort (x, n, k);

FOR i:=1 TO n DO WRITE(x[i], ’  ’);

END.