user
|  |
| --- |
| This page uses content from **Wikipedia**. The original article was at Cocktail sort. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance) |

The cocktail shaker sort is an improvement on the Bubble Sort.

The improvement is basically that values "bubble" both directions through the array, because on each iteration the cocktail shaker sort bubble sorts once forwards and once backwards. Pseudocode for the algorithm (from wikipedia):

```
function cocktailSort( A : list of sortable items )
 do
   swapped := false
   for each i in 0 to length( A ) - 2 do
     if A[ i ] > A[ i+1 ] then // test whether the two 
                               // elements are in the wrong 
                               // order
       swap( A[ i ], A[ i+1 ] ) // let the two elements
                                // change places
       swapped := true;
   if swapped = false then
     // we can exit the outer loop here if no swaps occurred.
     break do-while loop;
   swapped := false
   for each i in length( A ) - 2 down to 0 do
     if A[ i ] > A[ i+1 ] then
       swap( A[ i ], A[ i+1 ] )
       swapped := true;
 while swapped; // if no elements have been swapped, 
                // then the list is sorted

```

Related task
:   * cocktail sort with shifting bounds
assistant
(formerly Perl 6)

```
sub cocktail_sort ( @a ) {
    my $range = 0 ..^ @a.end;
    loop {
        my $swapped_forward = 0;
        for $range.list -> $i {
            if @a[$i] > @a[$i+1] {
                @a[ $i, $i+1 ] .= reverse;
                $swapped_forward = 1;
            } 
        }
        last if not $swapped_forward;

        my $swapped_backward = 0;
        for $range.reverse -> $i {
            if @a[$i] > @a[$i+1] {
                @a[ $i, $i+1 ] .= reverse;
                $swapped_backward = 1;
            }
        }
        last if not $swapped_backward;
    }
    return @a;
}

my @weights = (^50).map: { 100 + ( 1000.rand.Int / 10 ) };
say @weights.sort.Str eq @weights.&cocktail_sort.Str ?? 'ok' !! 'not ok';

```