Project: better partition

Xinok via Digitalmars-d digitalmars-d at puremagic.com
Sun May 22 14:33:47 PDT 2016


On Wednesday, 18 May 2016 at 19:54:19 UTC, Andrei Alexandrescu 
wrote:
> ...
> No worries. Please take anything you need from there for your 
> code, make it better, and contribute it back to the stdlib! -- 
> Andrei

As it turns out, easier said than done.  I've been thinking about 
it for a few days now but I don't see a simple way to optimally 
merge the two techniques. The way that I alternate between 
iterating "lo" and "hi" (or lef/rig in my code) doesn't really 
work when you need to keep the iterator stationary until 
something fills the vacancy.

This is the best solution I have so far and it doesn't feel like 
a good solution at that:

     for (;;)
     {
         ++lo;
         for (;;)
         {
             if(r[lo] < p)  ++lo; else break;
             if(r[lo] <= p) ++lo; else break;
         }

         if(lo > hi) lo = hi;
         r[hi] = r[lo];

         --hi;
         for (;;)
         {
             if(p < r[hi])  --hi; else break;
             if(p <= r[hi]) --hi; else break;
         }
         if(lo >= hi) break;
         r[lo] = r[hi];
     }

The idea is simple: alternate the check for equality in hopes of 
skipping some equal elements. Unfortunately, this modification 
requires a little more work and TWO sentinels at either end of 
the range because it may skip over the first.

In most real-world data, there's only marginal gains to be made 
in skipping over equal elements, too small to justify 
compromising the gains achieved by using sentinels and vacancies. 
So unless an optimal solution exists, it's just not worth it.


More information about the Digitalmars-d mailing list