Challenge: fair partition function
Andrei Alexandrescu via Digitalmars-d
digitalmars-d at puremagic.com
Mon Feb 8 15:25:00 PST 2016
Consider defining a function that partitions a range around a given
index like this:
size_t pivotPartition(alias less = (a, b) => a < b, Range)
(Range r, size_t pivot);
Returns x, one of the the indexes that r[pivot] would have if r were
sorted. Also, r[0 .. x] contains stuff no greater than r[x] and r[x + 1
.. $] contains stuff no less than r[x].
The challenge is to implement such a function with fairness: if several
elements are equal to r[pivot], return the index closest to r.length / 2.
The function should be efficient, minimize calls to less and swap, etc.
A variant that is efficient but does not implement fairness is below.
Andrei
size_t pivotPartition(alias less = (a, b) => a < b, Range)
(Range r, size_t pivot)
{
assert(pivot < r.length || r.length == 0 && pivot == 0);
if (r.length <= 1) return 0;
import std.algorithm : swapAt;
r.swapAt(pivot, 0);
size_t lo = 1, hi = r.length - 1;
loop: for (;;)
{
for (;; ++lo)
{
if (lo > hi) break loop;
if (less(r[0], r[lo])) break;
}
// found the left bound
assert(lo <= hi);
for (;; --hi)
{
if (lo == hi) break loop;
if (less(r[hi], r[0])) break;
}
// found the right bound, swap & make progress
r.swapAt(lo++, hi--);
}
--lo;
r.swapAt(lo, 0);
return lo;
}
More information about the Digitalmars-d
mailing list