mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-16 14:16:09 -06:00
124 lines
2.8 KiB
C++
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>());
|
|
}
|