#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <cassert>
//This sort needs to work on a series of "chunks" in a certain format.
// Each chunk is: 1 pivot followed by data < this pivot, but >= previous pivot
// Given data: 17,16,8,6,18,12,14,13,8,6,5,19,22,12,16,20,7,0,10,6,15,18,19,6
// We chunk it: [17,16,8,6,6,12,14,13,8,6,5,15,6,12,16,10,7,0],[20,18,19,18,19],[22]
// Then we iterate over the list, one chunk at a time: [17,16,8,6,6,12,14,13,8,6,5,15,6,12,16,10,7,0]
// splitting each chunk into two subchunks: [16,7,8,6,6,12,14,13,8,6,5,15,6,12,0,10],[17,16,]
// A chunk that is 1 element (only the pivot, no other data) is in the correct location.
template<class bidi_iterator, class predicate>
void inplace_sort(const bidi_iterator first, const bidi_iterator last, const predicate& pred) {
using std::swap;
if (first == last)
return;
bidi_iterator left = first;
//Rearrange the origional data into "Chunks"
while(left != last) {
bidi_iterator mid = std::partition(left+1, last, std::bind2nd(pred, *left));
left = mid;
}
bool again; //while there might still be unsorted data
do {
left = first; //iterate over data
again = false;
do { //iterate over each chunk
bidi_iterator next = std::next(left);
if (next == last)
break;
//skip chunks that are only the pivot.
//IE, find two elements out of order
while(std::next(next) != last && pred(*left, *next)) {
++left;
++next;
}
//find the end of the chunk
//IE next element bigger than pivot
bidi_iterator right = std::next(next);
int len=2;
while(right!=last && pred(*right, *left)) {
++len;
++right;
}
bidi_iterator mid = right; //arbitrary assignment
// if it's two, just swap
if (len == 2)
swap(*next, *left);
else {
//if more than two, partition into two seperate chunks
//first, select a new pivot (next) and partition
mid = std::partition(std::next(next), right, std::bind2nd(pred, *next));
//this means we have to move the pivots
//the new(next) pivot begins the first chunk
//the old(left) pivot begins the second chunk
swap(*left, *next);
bidi_iterator prev = std::prev(mid);
if (next != prev)
swap(*next, *prev);
//There might be more data, do another pass
again = true;
}
//move to the next chunk
left = right;
} while(left!=last); //continue until we do all the chunks in the data
} while(again); //continue until we're sorted
assert(std::is_sorted(first, last));
return;
}
template<class bidi_iterator>
void inplace_sort(bidi_iterator begin, bidi_iterator end) {
typedef typename std::iterator_traits<bidi_iterator>::value_type value_type;
return inplace_sort(begin, end, std::less<value_type>());
}
#include <cstdlib>
#include <ctime>
#include <vector>
template <typename T>
struct tracer : std::less<T> {
static int count;
bool operator()(T x, T y) const {
++count;
return std::less<T>::operator()(x, y);
}
};
template <typename T>
int tracer<T>::count = 0;
int main() {
unsigned test_size;
std::cin >> test_size;
double stdsort_time=0;
double inplacesort_time=0;
srand((unsigned)time(NULL));
std::vector<int> data(test_size);
for(unsigned i=0; i<data.size(); ++i)
data[i] = 10000+rand();
std::vector<int> data2;
{
data2 = data;
std::sort(data2.begin(), data2.end(), tracer<int>());
data2 = data;
clock_t begin = clock();
std::sort(data2.begin(), data2.end());
clock_t end = clock();
stdsort_time = double(end-begin)/CLOCKS_PER_SEC;
}
std::cout << "comparisons: " << tracer<int>::count << '\n';
tracer<int>::count = 0;
std::cout << "std::sort took " << stdsort_time << "s.\n";
{
data2 = data;
inplace_sort(data2.begin(), data2.end(), tracer<int>());
data2 = data;
clock_t begin = clock();
inplace_sort(data2.begin(), data2.end());
clock_t end = clock();
inplacesort_time = double(end-begin)/CLOCKS_PER_SEC;
}
std::cout << "comparisons: " << tracer<int>::count << '\n';
std::cout << "inplace_sort took " << inplacesort_time << "s.\n";
return 0;
}
I2luY2x1ZGUgPGFsZ29yaXRobT4KI2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPGl0ZXJhdG9yPgojaW5jbHVkZSA8Y2Fzc2VydD4KCi8vVGhpcyBzb3J0IG5lZWRzIHRvIHdvcmsgb24gYSBzZXJpZXMgb2YgImNodW5rcyIgaW4gYSBjZXJ0YWluIGZvcm1hdC4KLy8gRWFjaCBjaHVuayBpczogMSBwaXZvdCBmb2xsb3dlZCBieSBkYXRhIDwgdGhpcyBwaXZvdCwgYnV0ID49IHByZXZpb3VzIHBpdm90Ci8vICAgICBHaXZlbiBkYXRhOiAgMTcsMTYsOCw2LDE4LDEyLDE0LDEzLDgsNiw1LDE5LDIyLDEyLDE2LDIwLDcsMCwxMCw2LDE1LDE4LDE5LDYKLy8gICAgIFdlIGNodW5rIGl0OiBbMTcsMTYsOCw2LDYsMTIsMTQsMTMsOCw2LDUsMTUsNiwxMiwxNiwxMCw3LDBdLFsyMCwxOCwxOSwxOCwxOV0sWzIyXQovLyBUaGVuIHdlIGl0ZXJhdGUgb3ZlciB0aGUgbGlzdCwgb25lIGNodW5rIGF0IGEgdGltZTogIFsxNywxNiw4LDYsNiwxMiwxNCwxMyw4LDYsNSwxNSw2LDEyLDE2LDEwLDcsMF0KLy8gICAgc3BsaXR0aW5nIGVhY2ggY2h1bmsgaW50byB0d28gc3ViY2h1bmtzOiBbMTYsNyw4LDYsNiwxMiwxNCwxMyw4LDYsNSwxNSw2LDEyLDAsMTBdLFsxNywxNixdCi8vIEEgY2h1bmsgdGhhdCBpcyAxIGVsZW1lbnQgKG9ubHkgdGhlIHBpdm90LCBubyBvdGhlciBkYXRhKSBpcyBpbiB0aGUgY29ycmVjdCBsb2NhdGlvbi4KdGVtcGxhdGU8Y2xhc3MgYmlkaV9pdGVyYXRvciwgY2xhc3MgcHJlZGljYXRlPgp2b2lkIGlucGxhY2Vfc29ydChjb25zdCBiaWRpX2l0ZXJhdG9yIGZpcnN0LCBjb25zdCBiaWRpX2l0ZXJhdG9yIGxhc3QsIGNvbnN0IHByZWRpY2F0ZSYgcHJlZCkgewoJdXNpbmcgc3RkOjpzd2FwOwoJaWYgKGZpcnN0ID09IGxhc3QpCgkJcmV0dXJuOwoJYmlkaV9pdGVyYXRvciBsZWZ0ID0gZmlyc3Q7CgkvL1JlYXJyYW5nZSB0aGUgb3JpZ2lvbmFsIGRhdGEgaW50byAiQ2h1bmtzIgoJd2hpbGUobGVmdCAhPSBsYXN0KSB7CgkJYmlkaV9pdGVyYXRvciBtaWQgPSBzdGQ6OnBhcnRpdGlvbihsZWZ0KzEsIGxhc3QsIHN0ZDo6YmluZDJuZChwcmVkLCAqbGVmdCkpOwoJCWxlZnQgPSBtaWQ7Cgl9Cglib29sIGFnYWluOyAvL3doaWxlIHRoZXJlIG1pZ2h0IHN0aWxsIGJlIHVuc29ydGVkIGRhdGEKCWRvIHsKCQlsZWZ0ID0gZmlyc3Q7IC8vaXRlcmF0ZSBvdmVyIGRhdGEKCQlhZ2FpbiA9IGZhbHNlOwoJCWRvIHsgLy9pdGVyYXRlIG92ZXIgZWFjaCBjaHVuawoJCQliaWRpX2l0ZXJhdG9yIG5leHQgPSBzdGQ6Om5leHQobGVmdCk7CgkJCWlmIChuZXh0ID09IGxhc3QpIAoJCQkJYnJlYWs7CgkJCS8vc2tpcCBjaHVua3MgdGhhdCBhcmUgb25seSB0aGUgcGl2b3QuCgkJCS8vSUUsIGZpbmQgdHdvIGVsZW1lbnRzIG91dCBvZiBvcmRlcgoJCQl3aGlsZShzdGQ6Om5leHQobmV4dCkgIT0gbGFzdCAmJiBwcmVkKCpsZWZ0LCAqbmV4dCkpIHsKCQkJCSsrbGVmdDsKCQkJCSsrbmV4dDsKCQkJfQoJCQkvL2ZpbmQgdGhlIGVuZCBvZiB0aGUgY2h1bmsKCQkJLy9JRSBuZXh0IGVsZW1lbnQgYmlnZ2VyIHRoYW4gcGl2b3QKCQkJYmlkaV9pdGVyYXRvciByaWdodCA9IHN0ZDo6bmV4dChuZXh0KTsKCQkJaW50IGxlbj0yOwoJCQl3aGlsZShyaWdodCE9bGFzdCAmJiBwcmVkKCpyaWdodCwgKmxlZnQpKSB7CgkJCQkrK2xlbjsKCQkJCSsrcmlnaHQ7CgkJCX0KCQkJYmlkaV9pdGVyYXRvciBtaWQgPSByaWdodDsgLy9hcmJpdHJhcnkgYXNzaWdubWVudAoJCQkvLyBpZiBpdCdzIHR3bywganVzdCBzd2FwCgkJCWlmIChsZW4gPT0gMikKCQkJCXN3YXAoKm5leHQsICpsZWZ0KTsJCgkJCWVsc2UgeyAKCQkJCS8vaWYgbW9yZSB0aGFuIHR3bywgcGFydGl0aW9uIGludG8gdHdvIHNlcGVyYXRlIGNodW5rcwoJCQkJLy9maXJzdCwgc2VsZWN0IGEgbmV3IHBpdm90IChuZXh0KSBhbmQgcGFydGl0aW9uCgkJCQltaWQgPSBzdGQ6OnBhcnRpdGlvbihzdGQ6Om5leHQobmV4dCksIHJpZ2h0LCBzdGQ6OmJpbmQybmQocHJlZCwgKm5leHQpKTsJCgkJCQkvL3RoaXMgbWVhbnMgd2UgaGF2ZSB0byBtb3ZlIHRoZSBwaXZvdHMKCQkJCS8vdGhlIG5ldyhuZXh0KSBwaXZvdCBiZWdpbnMgdGhlIGZpcnN0IGNodW5rCgkJCQkvL3RoZSBvbGQobGVmdCkgcGl2b3QgYmVnaW5zIHRoZSBzZWNvbmQgY2h1bmsKCQkJCXN3YXAoKmxlZnQsICpuZXh0KTsKCQkJCWJpZGlfaXRlcmF0b3IgcHJldiA9IHN0ZDo6cHJldihtaWQpOwoJCQkJaWYgKG5leHQgIT0gcHJldikKCQkJCQlzd2FwKCpuZXh0LCAqcHJldik7CgkJCQkvL1RoZXJlIG1pZ2h0IGJlIG1vcmUgZGF0YSwgZG8gYW5vdGhlciBwYXNzCgkJCQlhZ2FpbiA9IHRydWU7CgkJCX0KCQkJLy9tb3ZlIHRvIHRoZSBuZXh0IGNodW5rCgkJCWxlZnQgPSByaWdodDsKCQl9IHdoaWxlKGxlZnQhPWxhc3QpOyAvL2NvbnRpbnVlIHVudGlsIHdlIGRvIGFsbCB0aGUgY2h1bmtzIGluIHRoZSBkYXRhCgl9IHdoaWxlKGFnYWluKTsgLy9jb250aW51ZSB1bnRpbCB3ZSdyZSBzb3J0ZWQKCWFzc2VydChzdGQ6OmlzX3NvcnRlZChmaXJzdCwgbGFzdCkpOwoJcmV0dXJuOwp9Cgp0ZW1wbGF0ZTxjbGFzcyBiaWRpX2l0ZXJhdG9yPgp2b2lkIGlucGxhY2Vfc29ydChiaWRpX2l0ZXJhdG9yIGJlZ2luLCBiaWRpX2l0ZXJhdG9yIGVuZCkgewoJdHlwZWRlZiB0eXBlbmFtZSBzdGQ6Oml0ZXJhdG9yX3RyYWl0czxiaWRpX2l0ZXJhdG9yPjo6dmFsdWVfdHlwZSB2YWx1ZV90eXBlOwoJcmV0dXJuIGlucGxhY2Vfc29ydChiZWdpbiwgZW5kLCBzdGQ6Omxlc3M8dmFsdWVfdHlwZT4oKSk7Cn0KCiNpbmNsdWRlIDxjc3RkbGliPgojaW5jbHVkZSA8Y3RpbWU+CiNpbmNsdWRlIDx2ZWN0b3I+CiAKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnN0cnVjdCB0cmFjZXIgOiBzdGQ6Omxlc3M8VD4gewogICAgc3RhdGljIGludCBjb3VudDsKIAogICAgYm9vbCBvcGVyYXRvcigpKFQgeCwgVCB5KSBjb25zdCB7CiAgICAgICAgKytjb3VudDsKICAgICAgICByZXR1cm4gc3RkOjpsZXNzPFQ+OjpvcGVyYXRvcigpKHgsIHkpOwogICAgfQp9Owp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4KaW50IHRyYWNlcjxUPjo6Y291bnQgPSAwOwogCmludCBtYWluKCkgewogICAgICAgIHVuc2lnbmVkIHRlc3Rfc2l6ZTsKICAgICAgICBzdGQ6OmNpbiA+PiB0ZXN0X3NpemU7CgoJZG91YmxlIHN0ZHNvcnRfdGltZT0wOwoJZG91YmxlIGlucGxhY2Vzb3J0X3RpbWU9MDsKCXNyYW5kKCh1bnNpZ25lZCl0aW1lKE5VTEwpKTsKCXN0ZDo6dmVjdG9yPGludD4gZGF0YSh0ZXN0X3NpemUpOwoJZm9yKHVuc2lnbmVkIGk9MDsgaTxkYXRhLnNpemUoKTsgKytpKQoJCWRhdGFbaV0gPSAxMDAwMCtyYW5kKCk7CglzdGQ6OnZlY3RvcjxpbnQ+IGRhdGEyOwoJewoJCWRhdGEyID0gZGF0YTsKCQlzdGQ6OnNvcnQoZGF0YTIuYmVnaW4oKSwgZGF0YTIuZW5kKCksIHRyYWNlcjxpbnQ+KCkpOwoJCWRhdGEyID0gZGF0YTsKCQljbG9ja190IGJlZ2luID0gY2xvY2soKTsKCQlzdGQ6OnNvcnQoZGF0YTIuYmVnaW4oKSwgZGF0YTIuZW5kKCkpOwoJCWNsb2NrX3QgZW5kID0gY2xvY2soKTsKCQlzdGRzb3J0X3RpbWUgPSBkb3VibGUoZW5kLWJlZ2luKS9DTE9DS1NfUEVSX1NFQzsKCX0KICAgICAgICBzdGQ6OmNvdXQgPDwgImNvbXBhcmlzb25zOiAiIDw8IHRyYWNlcjxpbnQ+Ojpjb3VudCA8PCAnXG4nOwogICAgICAgIHRyYWNlcjxpbnQ+Ojpjb3VudCA9IDA7CglzdGQ6OmNvdXQgPDwgInN0ZDo6c29ydCAgICB0b29rICIgPDwgc3Rkc29ydF90aW1lIDw8ICJzLlxuIjsKCXsKCQlkYXRhMiA9IGRhdGE7CgkJaW5wbGFjZV9zb3J0KGRhdGEyLmJlZ2luKCksIGRhdGEyLmVuZCgpLCB0cmFjZXI8aW50PigpKTsKCQlkYXRhMiA9IGRhdGE7CgkJY2xvY2tfdCBiZWdpbiA9IGNsb2NrKCk7CgkJaW5wbGFjZV9zb3J0KGRhdGEyLmJlZ2luKCksIGRhdGEyLmVuZCgpKTsKCQljbG9ja190IGVuZCA9IGNsb2NrKCk7CgkJaW5wbGFjZXNvcnRfdGltZSA9IGRvdWJsZShlbmQtYmVnaW4pL0NMT0NLU19QRVJfU0VDOwoJfQogICAgICAgIHN0ZDo6Y291dCA8PCAiY29tcGFyaXNvbnM6ICIgPDwgdHJhY2VyPGludD46OmNvdW50IDw8ICdcbic7CglzdGQ6OmNvdXQgPDwgImlucGxhY2Vfc29ydCB0b29rICIgPDwgaW5wbGFjZXNvcnRfdGltZSA8PCAicy5cbiI7CglyZXR1cm4gMDsKfQo=