dimanche 2 août 2015

Implementing Bentley-McIlroy three way partitioning

I implemented this algorithm base on a question of Robert Sedgewick's book Algorithms 4th edition. The problem is that the partitioning doesn't always behaves as I will expect (sometimes the invariant doesn't hold ). But when used with Quicksort it does end up sorting the unput.

This is mi implementation:

void Bentley_McIlroy(int*& lo, int*& hi )
{

        using std::swap;

        int pivot = *lo;
        int *j = lo, *i = hi--, *p = lo + 1, *q = hi;

        while (true)
        {
            while (pivot < *(--i));
            while (*(++j) < pivot) if (j == hi) break;
            if (j >= i) break;
            swap(*i, *j);

            if (*i == pivot) swap(*q--, *i);
            if (*j == pivot) swap(*p++, *j);
        }
        int min = std::min(p - lo, i - p + 1);
        for (int f = 0; f < min; ++f)
            swap(*(lo + f), *(i - f));

        int min2 = std::min(hi - q, q - i++);
        for (int f = 0; f < min2; ++f)
            swap(*(hi - f), *(i + f));

        lo = i - (p - lo);
        hi = i + (hi - q);

}

I practically copy the algorithm posted here by Robert Sedgewick and Bentley himself: http://ift.tt/1K0nE3b. With some small modifications (r is one past the end).

void Bentley_McIlroy(int*& l, int*& r )
{

        r--;    
        using std::swap;

        auto i = l - 1, j = r, p = l - 1, q = r; int v = *r;
        if (r <= l) return;
        for (;;)
        {
            while (*(++i) < v);
            while (v < *(--j)) if (j == l) break;
            if (i >= j) break;
            swap(*i, *j);
            if (*i == v) { p++; swap(*p, *i); }
            if (v == *j) { q--; swap(*j, *q); }
        }

        swap(*i, *r); j = i - 1; i = i + 1;
        for (auto k = l; k < p; k++, j--) swap(*k, *j);
        for (auto k = r - 1; k > q; k--, i++) swap(*i, *k);

        l = j + 1;
        r = i;

}

In both implementations for some cases not all numbers equal to the pivot end up in the center. Is this behavior expected (I am guessing is not) if not what could be wrong with this implementations?

Aucun commentaire:

Enregistrer un commentaire