I have been working on sorting algorithms for a few weeks now, but one of my question still hasn't an answer: are there optimal sequential comparison sorts for fixed-size – and random-access – collections? Most sorting algorithms adapt to the size of the collection, but knowing the size of the collection to sort allows to pick a specific sorting algorithm for this size. For example, the following algorithm should sort three values with both an optimal number of comparisons and an optimal number of swaps or assignments (it's C++, but it should be fairly easy to translate to any language):
void sort3(int& x, int& y, int& z) { if (x < y) { if (z < y) { if (z < x) { int tmp = z; z = y; y = x; x = tmp; } else { std::swap(y, z); } } } else if (z < y) { std::swap(x, z); } else if (z < x) { int tmp = x; x = y; y = z; z = tmp; } else { std::swap(x, y); } }
Whatever the input, this algorithm will sort three values with at most 3 comparisons and 4 assignments. I may be wrong, but I don't think that sorting three values can be done with less comparisons and less assignments than this algorithm. If it is indeed the case, then this would be an optimal comparison sorting algorithm to sort three values.
It seems that optimal sorting algorithms of this kind for any size could be generated thanks to some permutation algorithm, but I was unable to find such a generation algorithm and writing one does not seem to be trivial. I tried to find near-optimal sorting algorithms for some fixed sizes, but couldn't find any simple way to generate such algorithms:
Sorting networks seemed like a good idea but they always perform a fixed number of comparisons and swaps, which means that they do not adapt to the data. Even optimal sorting networks of size greater than 5 qickly lose the battle against a simple insertion sort for some inputs.
Parallel sorting algorithms and non-comparison sorts (spreadsort, radix sort...) are interesting but I am interested in sequentially sorting small collections. And these categories of algorithms tend to hide a big constant complexity, which means that they are more suitable for big collections.
My current method to find the most optimal sorting algorithm to sort a small fixed-size collection is to count the number of comparisons needed to sort all the possible permutations of a collection of size N:
// Fill an array of size N std::array<int, N> collection; std::iota(std::begin(collection), std::end(collection), 0); // Count comparisons made by an insertion sort cppsort::counting_adapter< cppsort::insertion_sorter > sorter; // Total number of comparisons std::size_t count = 0; // For each possible permutation of collection do { auto to_sort = collection; // Sort collection, get the number of comparisons made count += sorter(to_sort); } while (std::next_permutation(std::begin(collection), std::end(collection)));
This code uses my cpp-sort library. I used it because it makes it easy to count comparisons made by a sorting algorithm, but it could be implemented without it or in another language. This method has a problem though: it only takes into account the number of comparisons and can only help to find the most optimal algorithm amongst known algorithms, it doesn't allow to write a sorting algorithms generators.
That was quite the introduction, but my question is basically as follows: are there known methods to generate sequential comparison sorting algorithms for fixed-size collections that are optimal with regards to the number of assignments and/or the number of comparisons performed?