7

While going through Wikipedia's list of sorting algorithms I noticed that there's no stable comparison sort that has O(n*log(n)) (worst-case) time-complexity and O(1) (worst-case) space-complexity. This surely looks like a theoretical boundary, but I couldn't find more information about it.

How would one proof this?

Note: I know about the lower limit of O(n*log(n)) worst-case time-complexity for comparison sorts.

Florian Brucker
  • 9,621
  • 3
  • 48
  • 81

2 Answers2

9

Despite what that article says, in-place stable Merge Sort can be made O(n log n).

Here is a paper that explains two ways to implement it.

BlueRaja - Danny Pflughoeft
  • 84,206
  • 33
  • 197
  • 283
  • 2
    Is the sort described in that paper actually stable? I'm not sure, as they only talk about stability at the end, as if it's an additional goal (and merge sort does not necessarily imply stable, it's possible to write one that isn't). I haven't implemented either of the algorithms shown, but judging by the diagrams neither are stable (see changing of order of large blocks of data). –  Mar 19 '12 at 23:09
  • 1
    My apologies, on further inspection, I think the second variant can definitely be made stable, although I'm still not sure the first is. –  Mar 19 '12 at 23:21
1

Here is a complete C++ implementation which I converted from the C implementation here:

#include <algorithm>
#include <functional>

template<class It>
It rotate(It begin, It const middle, It end)
{
    typename std::iterator_traits<It>::difference_type i = 0, j;
    if (begin != middle && middle != end)
    {
        while ((i = std::distance(begin, middle)) !=
               (j = std::distance(middle, end)))
        {
            It k = middle;
            std::advance(
                k,
                std::max(
                    typename std::iterator_traits<It>::difference_type(),
                    j - i));
            std::swap_ranges(k, end, begin);
            if (i > j) { std::advance(begin, j); }
            else { std::advance(end, -i); }
        }
    }
    return std::swap_ranges(middle - i, middle, middle);
}

template<class It, class Less>
It bsearch(
    It begin, It left, It right,
    typename std::iterator_traits<It>::difference_type n,
    Less &less)
{
    while (left < right)
    {
        It const middle = left + std::distance(left, right) / 2;
        bool const b = !less(
            *(begin + (std::distance(middle, begin) + n)),
            *middle);
        (b ? left : right) = middle + b;
    }
    return left;
}

template<class It, class Less>
void merge(It const begin, It const middle, It const end, Less &less)
{
    bool naive_insertion_optimization = false;
    if (naive_insertion_optimization && std::distance(begin, end) < 0)
    {
        for (It i = middle; i != end; ++i)
        {
            for (It p = i; p != begin; --p)
            {
                if (!less(*p, *(p - 1)))
                {
                    break;
                }
                using std::iter_swap;
                iter_swap(p, p - 1);
            }
        }
    }
    else if (begin < middle && middle < end)
    {
        typename std::iterator_traits<It>::difference_type const
            half = std::distance(begin, end) / 2,
            left = std::distance(begin, middle),
            right = std::distance(middle, end);
        It const midpoint = begin + half;
        bool const b = left > right;
        It const i = bsearch(
            begin,
            b ? midpoint - right : begin,
            b ? midpoint : middle,
            half + left - 1,
            less);
        rotate(i, middle, begin + (std::distance(i, middle) + half));
        merge(begin, i, midpoint, less);
        merge(midpoint, midpoint + std::distance(i, middle), end, less);
    }
}

template<class It, class Less>
void sort(It const begin, It const end, Less &less)
{
    if (std::distance(begin, end) > 1)
    {
        It const middle = begin + std::distance(begin, end) / 2;
        sort(begin, middle, less);
        sort(middle, end, less);
        merge(begin, middle, end, less);
    }
}

template<class It>
void sort(It const begin, It const end)
{
    std::less<typename std::iterator_traits<It>::value_type> less;
    return sort(begin, end, less);
}
Community
  • 1
  • 1
user541686
  • 205,094
  • 128
  • 528
  • 886