#include <iostream>
#include <vector>
#include <limits>
#include <type_traits>
template <typename It>
It radix_sort_recurse(It start, It stop, unsigned bit, unsigned last_bit) {
if(start == stop)
return stop;
const unsigned bitmask = 1 << bit;
It left = start;
It right = stop;
right--; //make right point to a valid element
//loop until all elements have been partitioned
//afterwards left will point AFTER the last left element
while(left <= right) {
if(*left & bitmask) std::swap(*left, *right--);
else left++;
}
//recurse on left and right partitions
if(bit > last_bit) {
radix_sort_recurse(start, left, bit-1, last_bit);
radix_sort_recurse(left, stop, bit-1, last_bit);
}
return left;
}
template <typename It>
void radix_parity_sort(It start, It stop) {
using int_t = typename std::remove_reference<decltype(*start)>::type;
//count the bits
constexpr auto digits = std::numeric_limits<int_t>::digits;
constexpr auto bits = digits + std::is_signed<int_t>::value;
//partition based on parity
auto p = radix_sort_recurse(start, stop, 0, 0);
//msb radix sort on rest of bits
radix_sort_recurse(start, p, bits-1, 1);
radix_sort_recurse(p, stop, bits-1, 1);
}
int main() {
std::vector<int> v = {
43, 380, 246, 807, 510, 433, 878, 78, 789, 103, 492, 543, 895,
439, 466, 199, 614, 867, 3, 458, 953, 554, 561, 501, 324, 859,
636, 768, 251, 201, 305, 435, 790, 357, 55, 739, 751, 704, 408,
665, 104, 86, 255, 46, 103, 311, 265, 85, 155, 794, 704, 56,
909, 783, 892, 562, 289, 805, 400, 394, 541, 959, 335, 263, 2,
57, 999, 9, 450, 696, 341, 521, 137, 448, 454, 411, 144, 773,
750, 821, 711, 926, 224, 882, 717, 157, 488, 26, 126, 945, 710,
702, 29, 109, 301, 176, 382, 46, 175, 360
};
radix_parity_sort(v.begin(), v.end());
for(auto e : v)
std::cout << e << " ";
std::cout << "\n";
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8bGltaXRzPgojaW5jbHVkZSA8dHlwZV90cmFpdHM+Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSXQ+Ckl0IHJhZGl4X3NvcnRfcmVjdXJzZShJdCBzdGFydCwgSXQgc3RvcCwgdW5zaWduZWQgYml0LCB1bnNpZ25lZCBsYXN0X2JpdCkgewoJaWYoc3RhcnQgPT0gc3RvcCkKCQlyZXR1cm4gc3RvcDsKCWNvbnN0IHVuc2lnbmVkIGJpdG1hc2sgPSAxIDw8IGJpdDsKCUl0IGxlZnQgPSBzdGFydDsKCUl0IHJpZ2h0ID0gc3RvcDsKCXJpZ2h0LS07IC8vbWFrZSByaWdodCBwb2ludCB0byBhIHZhbGlkIGVsZW1lbnQKCS8vbG9vcCB1bnRpbCBhbGwgZWxlbWVudHMgaGF2ZSBiZWVuIHBhcnRpdGlvbmVkCgkvL2FmdGVyd2FyZHMgbGVmdCB3aWxsIHBvaW50IEFGVEVSIHRoZSBsYXN0IGxlZnQgZWxlbWVudAoJd2hpbGUobGVmdCA8PSByaWdodCkgewoJCWlmKCpsZWZ0ICYgYml0bWFzaykgc3RkOjpzd2FwKCpsZWZ0LCAqcmlnaHQtLSk7CgkJZWxzZSAgICAgICAgICAgICAgICBsZWZ0Kys7Cgl9CgkvL3JlY3Vyc2Ugb24gbGVmdCBhbmQgcmlnaHQgcGFydGl0aW9ucwoJaWYoYml0ID4gbGFzdF9iaXQpIHsKCQlyYWRpeF9zb3J0X3JlY3Vyc2Uoc3RhcnQsIGxlZnQsIGJpdC0xLCBsYXN0X2JpdCk7CgkJcmFkaXhfc29ydF9yZWN1cnNlKGxlZnQsICBzdG9wLCBiaXQtMSwgbGFzdF9iaXQpOwoJfQoJcmV0dXJuIGxlZnQ7Cn0KCgp0ZW1wbGF0ZSA8dHlwZW5hbWUgSXQ+CnZvaWQgcmFkaXhfcGFyaXR5X3NvcnQoSXQgc3RhcnQsIEl0IHN0b3ApIHsKCXVzaW5nIGludF90ID0gdHlwZW5hbWUgc3RkOjpyZW1vdmVfcmVmZXJlbmNlPGRlY2x0eXBlKCpzdGFydCk+Ojp0eXBlOwoJLy9jb3VudCB0aGUgYml0cwoJY29uc3RleHByIGF1dG8gZGlnaXRzID0gc3RkOjpudW1lcmljX2xpbWl0czxpbnRfdD46OmRpZ2l0czsKCWNvbnN0ZXhwciBhdXRvIGJpdHMgPSBkaWdpdHMgKyBzdGQ6OmlzX3NpZ25lZDxpbnRfdD46OnZhbHVlOyAKCQoJLy9wYXJ0aXRpb24gYmFzZWQgb24gcGFyaXR5CglhdXRvIHAgPSByYWRpeF9zb3J0X3JlY3Vyc2Uoc3RhcnQsIHN0b3AsIDAsIDApOwoJCgkvL21zYiByYWRpeCBzb3J0IG9uIHJlc3Qgb2YgYml0cwoJcmFkaXhfc29ydF9yZWN1cnNlKHN0YXJ0LCBwLCAgICBiaXRzLTEsIDEpOwoJcmFkaXhfc29ydF9yZWN1cnNlKHAsICAgICBzdG9wLCBiaXRzLTEsIDEpOwp9CgppbnQgbWFpbigpIHsKCXN0ZDo6dmVjdG9yPGludD4gdiA9IHsKCQk0MywgMzgwLCAyNDYsIDgwNywgNTEwLCA0MzMsIDg3OCwgNzgsIDc4OSwgMTAzLCA0OTIsIDU0MywgODk1LAoJCTQzOSwgNDY2LCAxOTksIDYxNCwgODY3LCAzLCA0NTgsIDk1MywgNTU0LCA1NjEsIDUwMSwgMzI0LCA4NTksCgkJNjM2LCA3NjgsIDI1MSwgMjAxLCAzMDUsIDQzNSwgNzkwLCAzNTcsIDU1LCA3MzksIDc1MSwgNzA0LCA0MDgsCgkJNjY1LCAxMDQsIDg2LCAyNTUsIDQ2LCAxMDMsIDMxMSwgMjY1LCA4NSwgMTU1LCA3OTQsIDcwNCwgNTYsCgkJOTA5LCA3ODMsIDg5MiwgNTYyLCAyODksIDgwNSwgNDAwLCAzOTQsIDU0MSwgOTU5LCAzMzUsIDI2MywgMiwKCQk1NywgOTk5LCA5LCA0NTAsIDY5NiwgMzQxLCA1MjEsIDEzNywgNDQ4LCA0NTQsIDQxMSwgMTQ0LCA3NzMsCgkJNzUwLCA4MjEsIDcxMSwgOTI2LCAyMjQsIDg4MiwgNzE3LCAxNTcsIDQ4OCwgMjYsIDEyNiwgOTQ1LCA3MTAsCgkJNzAyLCAyOSwgMTA5LCAzMDEsIDE3NiwgMzgyLCA0NiwgMTc1LCAzNjAKCX07CglyYWRpeF9wYXJpdHlfc29ydCh2LmJlZ2luKCksIHYuZW5kKCkpOwoJZm9yKGF1dG8gZSA6IHYpCgkJc3RkOjpjb3V0IDw8IGUgPDwgIiAiOwoJc3RkOjpjb3V0IDw8ICJcbiI7Cn0=