# What is Cocktail Sort

**also known as cocktail shaker sort or bidirectional bubble sort, is a sorting algorithm that works by repeatedly traversing a list of items in both directions, swapping adjacent elements if they are in the wrong order.**

Cocktail sort,

Cocktail sort,

To picture it, imagine a bartender making a cocktail. They start by picking up the shaker and shaking it up and down to mix the ingredients. Similarly, the algorithm starts by going through the list from left to right and swapping any adjacent items that are out of order.

Once it reaches the end of the list, it switches directions and goes back through the list from right to left, again swapping adjacent elements that are in the wrong order. This process is repeated until no more swaps are necessary, at which point the list is considered sorted.

Overall, cocktail sort is similar to bubble sort, but it has the added benefit of sorting the list in both directions, which can sometimes result in faster sorting times.

## Who invented it?

The inventor of cocktail sort is not clear as it has been independently discovered and developed by multiple people over the years. However, it is known that the algorithm has been around since the early 20th century and has been used in various forms in different applications. The name "cocktail sort" is said to have been coined in the 1940s by computer scientist and mathematician Donald Knuth in his book "The Art of Computer Programming," in reference to the shuffling action of the algorithm.

## Pseudocode

```
function block_sort(list, block_size):
// Divide the list into blocks of size `block_size`
blocks = []
for i = 0 to length of list, increment by `block_size`:
block = list[i:i+block_size]
blocks.append(block)
// Sort each block using a comparison-based sorting algorithm (e.g. quicksort)
for i = 0 to length of blocks:
sort(blocks[i])
// Merge the sorted blocks back together into a single sorted list
result = []
while length of blocks > 0:
min_block = find_minimum_block(blocks)
result.append(min_block.pop(0))
if length of min_block > 0:
blocks.add(min_block)
else:
remove min_block from blocks
return result
function find_minimum_block(blocks):
min_block = blocks[0]
for block in blocks:
if block[0] < min_block[0]:
min_block = block
return min_block
```

- The algorithm takes an array of elements as input.

- The variable `n` is set to the length of the array, and two more variables `start` and `end` are initialized to the first and last indices of the array, respectively.

- The algorithm then enters a while loop that continues as long as any swaps are made during the traversals of the array.

- Inside the loop, the algorithm first traverses the array from left to right, comparing adjacent elements and swapping them if they are in the wrong order. If any swaps are made, the `is_swapped` flag is set to `true`.

- If no swaps were made during the left-to-right traversal, the loop is exited early, since the array is already sorted.

- Otherwise, the algorithm traverses the array from right to left, again comparing adjacent elements and swapping them if necessary. If any swaps are made, the `is_swapped` flag is set to `true`.

- If no swaps were made during the right-to-left traversal, the loop is exited early, since the array is already sorted.

- The `start` and `end` variables are adjusted to exclude the elements that have already been sorted, and the loop repeats from the top.

- Once the loop is exited, the sorted array is returned as output.

- The variable `n` is set to the length of the array, and two more variables `start` and `end` are initialized to the first and last indices of the array, respectively.

- The algorithm then enters a while loop that continues as long as any swaps are made during the traversals of the array.

- Inside the loop, the algorithm first traverses the array from left to right, comparing adjacent elements and swapping them if they are in the wrong order. If any swaps are made, the `is_swapped` flag is set to `true`.

- If no swaps were made during the left-to-right traversal, the loop is exited early, since the array is already sorted.

- Otherwise, the algorithm traverses the array from right to left, again comparing adjacent elements and swapping them if necessary. If any swaps are made, the `is_swapped` flag is set to `true`.

- If no swaps were made during the right-to-left traversal, the loop is exited early, since the array is already sorted.

- The `start` and `end` variables are adjusted to exclude the elements that have already been sorted, and the loop repeats from the top.

- Once the loop is exited, the sorted array is returned as output.

## Sample Code

```
// C++ code snippet
vector
``` block_sort(vector list, int block_size) {
// Divide the list into blocks of size `block_size`
vector> blocks;
for (int i = 0; i < list.size(); i += block_size) {
vector block(list.begin() + i, list.begin() + i + block_size);
blocks.push_back(block);
}
// Sort each block using a comparison-based sorting algorithm (e.g. quicksort)
for (int i = 0; i < blocks.size(); i++) {
sort(blocks[i].begin(), blocks[i].end());
}
// Merge the sorted blocks back together into a single sorted list
vector result;
while (blocks.size() > 0) {
vector min_block = blocks[0];
int min_index = 0;
for (int i = 1; i < blocks.size(); i++) {
if (blocks[i][0] < min_block[0]) {
min_block = blocks[i];
min_index = i;
}
}
result.push_back(min_block[0]);
min_block.erase(min_block.begin());
if (min_block.size() > 0) {
blocks[min_index] = min_block;
} else {
blocks.erase(blocks.begin() + min_index);
}
}
return result;
}
int main() {
vector list = { 5, 3, 8, 4, 2, 7, 1, 6 };
int block_size = 3;
vector sorted_list = block_sort(list, block_size);
// Print the sorted list
for (int i = 0; i < sorted_list.size(); i++) {
cout << sorted_list[i] << " ";
}
cout << endl;
return 0;
}

```
# Python code snippet
def block_sort(lst, block_size):
# Divide the list into blocks of size `block_size`
blocks = [lst[i:i+block_size] for i in range(0, len(lst), block_size)]
# Sort each block using a comparison-based sorting algorithm (e.g. quicksort)
for i in range(len(blocks)):
blocks[i].sort()
# Merge the sorted blocks back together into a single sorted list
result = []
while len(blocks) > 0:
min_block = blocks[0]
min_index = 0
for i in range(1, len(blocks)):
if blocks[i][0] < min_block[0]:
min_block = blocks[i]
min_index = i
result.append(min_block.pop(0))
if len(min_block) > 0:
blocks[min_index] = min_block
else:
blocks.pop(min_index)
return result
# Example usage
lst = [5, 3, 8, 4, 2, 7, 1, 6]
block_size = 3
sorted_lst = block_sort(lst, block_size)
print(sorted_lst)
```

```
import java.util.*;
public class BlockSort {
public static List
``` blockSort(List list, int blockSize) {
// Divide the list into blocks of size `blockSize`
List> blocks = new ArrayList<>();
for (int i = 0; i < list.size(); i += blockSize) {
List block = list.subList(i, Math.min(i + blockSize, list.size()));
blocks.add(block);
}
// Sort each block using a comparison-based sorting algorithm (e.g. quicksort)
for (int i = 0; i < blocks.size(); i++) {
Collections.sort(blocks.get(i));
}
// Merge the sorted blocks back together into a single sorted list
List result = new ArrayList<>();
while (blocks.size() > 0) {
List minBlock = blocks.get(0);
int minIndex = 0;
for (int i = 1; i < blocks.size(); i++) {
if (blocks.get(i).get(0) < minBlock.get(0)) {
minBlock = blocks.get(i);
minIndex = i;
}
}
result.add(minBlock.get(0));
minBlock.remove(0);
if (minBlock.size() > 0) {
blocks.set(minIndex, minBlock);
} else {
blocks.remove(minIndex);
}
}
return result;
}
public static void main(String[] args) {
List list = Arrays.asList(5, 3, 8, 4, 2, 7, 1, 6);
int blockSize = 3;
List sortedList = blockSort(list, blockSize);
// Print the sorted list
System.out.println(sortedList);
}
}

## Time and Space Complexity

- The time complexity of Cocktail sort is O(n^2) in both the worst and average cases, where n is the number of elements in the array. This is because the algorithm consists of nested loops that iterate over the entire array multiple times.
- The space complexity of Cocktail sort is O(1), meaning it uses a constant amount of additional memory to sort the array. This is because it only swaps adjacent elements in the array, and does not require any additional data structures to perform the sort.

## Advantages

- Cocktail sort is a stable sorting algorithm, meaning that it preserves the relative order of equal elements in the input array.
- It can perform slightly better than bubble sort in some cases, as it also traverses the array in both directions, which can help it avoid repeatedly swapping the same elements back and forth.
- It can be useful in certain scenarios where data is mostly sorted, as it has a best-case time complexity of O(n).

## Disadvantages

- Cocktail sort has a worst-case and average-case time complexity of O(n^2), which can make it slow for large input arrays.
- It is not an efficient sorting algorithm for general-purpose use, as other algorithms like quicksort, mergesort, and heapsort generally perform better in terms of time complexity.
- Cocktail sort has a low practical value, as it is not often used in real-world applications due to its poor performance.