ultimatepp/uppdev/StableSort/StableSort2.h
cxl 351994a6cc Adding uppdev....
git-svn-id: svn://ultimatepp.org/upp/trunk@328 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2008-08-15 08:36:24 +00:00

124 lines
2.8 KiB
C++

// This does not work!
template <class I, class Comp>
inline bool I2less(I a, I b, int *ia, int *ib, const Comp& cmp)
{
int q = cmp(*a, *b);
return q == 0 ? *ia < *ib : q < 0;
}
template <class I, class Comp>
void I2ForwardSort(I begin, I end, int *ibegin, int *iend, const Comp& cmp)
{
if(begin == end)
return;
I limit = end;
int *ilimit = iend;
--limit, --ilimit;
while(!(begin == limit))
{
I best = limit, next = limit, ptr = limit;
int *ibest = limit, *inext = limit, *iptr = limit;
for(;;) {
if(!I2less(best, --ptr, ibest, --iptr, cmp)) {
if(ptr == begin) {
begin = next, ibegin = inext;
break;
}
}
else {
do {
if(ptr == begin) {
IterSwap(begin, best), IterSwap(ibegin, ibest);
++begin, ++ibegin;
goto NEXT_ITEM;
}
}
while(I2less(best, --ptr, ibest, --iptr, cmp));
if(ptr == begin) {
IterSwap(++begin, best), IterSwap(++ibegin, ibest);
++begin, ++ibegin;
break;
}
next = ptr, inext = iptr;
++next, ++inext;
}
best = ptr, ibest = iptr;
}
NEXT_ITEM:
;
}
}
template <class I, class Comp>
void QStableSort_(I begin, I end, int *ibegin, int *iend, const Comp& cmp)
{
int count;
while((count = (int)(end - begin)) > __SORT_THRESHOLD) {
int expected = count >> 1, deviation = expected - (expected >> 8);
I b = begin, e = end, m = b + expected;
int *ib = ibegin, *ie = iend, *im = ib + expected;
for(int pass = 1;; pass++) {
for(;; ++b) {
while(I2less(m, --e, im, --ie, cmp))
;
while(I2less(b, m, ib, im, cmp))
++b, ++ib;
if(!(b < e))
break;
if(m == b)
m = e, im = ie;
else
if(m == e)
m = b, im = ib;
IterSwap(b, e);
IterSwap(ib, ie);
}
if(pass >= __SORT_MEDIAN_PASSES)
break;
int pos = (int)(b - begin);
if(pos <= expected - deviation) {
e = end;
ie = iend;
}
else if(pos >= expected + deviation) {
e = b;
b = begin;
ie = ib;
ib = ibegin;
}
else
break;
pos = 1 + (int)((unsigned)rand() % (e - b - 2));
m = b + pos;
im = ib + pos;
}
if(b - begin < end - e) {
QStableSort_(begin, b, ibegin, ib, cmp);
begin = b;
ibegin = ib;
}
else {
QStableSort_(b, end, ibegin, iend, cmp);
end = b;
iend = ib;
}
}
if(count >= 2)
I2ForwardSort(begin, end, ibegin, iend, cmp);
}
template <class T>
struct StdCompare {
int operator()(const T& a, const T& b) const { return SgnCompare(a, b); }
};
template <class C>
void QStableSort(C& c)
{
Buffer<int> temp(c.GetCount());
for(int i = 0; i < c.GetCount(); i++)
temp[i] = i;
QStableSort_(c.Begin(), c.End(), ~temp, ~temp + c.GetCount(), StdCompare<C::ValueType>());
}