snippetcppMinor
Generic radix sort
Viewed 0 times
genericradixsort
Problem
This started out with my answer to Radix Sort on an Array of Strings?. Since I intend to write a generic radix sort for my own purposes anyway, I continued a little bit, and here is a version tested on:
-
a fixed
-
an
I will eventually make this more and more generic, but I am posting it here before it becomes extremely abstract. For now, it is not even parametrized with respect to ascending/descending order, but most interesting generalizations will be towards
Here it is (live example):
```
#include
#include
#include
#include
#include
#include
#include
template
using expr = std::integral_constant;
//-----------------------------------------------------------------------------
template
class radix_sort
{
template
void sort(I& idx, const S& slice) const
{
using A = std::array;
A count = {};
I prev = idx;
for (auto i : prev)
++count[slice(i)];
A offset = {{0}};
std::partial_sum(count.begin(), count.end() - 1, offset.begin() + 1);
for (auto i : prev)
idx[offset[slice(i)]++] = i;
}
public:
template
std::vector operator()(const D& data) const
{
std::vector idx(data.size());
std::iota(idx.begin(), idx.end(), 0);
if (data.size() (), data[i], digit));
});
}
return idx;
}
};
//----
-
a fixed
std::array of unsigned numbers, each treated as a fixed sequence of bytes from least-significant (right) to most-significant (left), to be sorted by natural order; and-
an
std::vector of std::strings, each treated as a variable-length sequence of characters from left to right, to be sorted by lexicographical order.I will eventually make this more and more generic, but I am posting it here before it becomes extremely abstract. For now, it is not even parametrized with respect to ascending/descending order, but most interesting generalizations will be towards
- all scalar types: signed integers, floating-point,
enums, pointers, etc.;
- sequences (built-in arrays or standard containers) of previous types to be sorted lexicographically;
- tuples or structures of previous types to be sorted lexicographically;
- recursive application of the above.
Here it is (live example):
```
#include
#include
#include
#include
#include
#include
#include
template
using expr = std::integral_constant;
//-----------------------------------------------------------------------------
template
class radix_sort
{
template
void sort(I& idx, const S& slice) const
{
using A = std::array;
A count = {};
I prev = idx;
for (auto i : prev)
++count[slice(i)];
A offset = {{0}};
std::partial_sum(count.begin(), count.end() - 1, offset.begin() + 1);
for (auto i : prev)
idx[offset[slice(i)]++] = i;
}
public:
template
std::vector operator()(const D& data) const
{
std::vector idx(data.size());
std::iota(idx.begin(), idx.end(), 0);
if (data.size() (), data[i], digit));
});
}
return idx;
}
};
//----
Solution
Style
You should reorder your headers in alphabetic order. It will help when you will have to check whether a header is already included or not:
You have many type names that are a single capital letter, which quite hinder readability. For example, you could change
You should also be consistent when naming your types: do you want them to be capitalized or not? If you want to be consistent, you could for example rename
Generally speaking, the style is quite good: the indentation is clear, the lines are not too long and you don't seem to have any magic number besides
Idiomacity
In
You should reorder your headers in alphabetic order. It will help when you will have to check whether a header is already included or not:
#include
#include
#include
#include
#include
#include
#include You have many type names that are a single capital letter, which quite hinder readability. For example, you could change
A into Arr. For many of them, I can't guess which "concept" should satisfy template parameter types. Apart from T and U for any type or N for any integral value, it is pretty uncommon to use a single capital letter.You should also be consistent when naming your types: do you want them to be capitalized or not? If you want to be consistent, you could for example rename
expr into Expr.Generally speaking, the style is quite good: the indentation is clear, the lines are not too long and you don't seem to have any magic number besides
0xFF. I wish I could always read code that clean.Idiomacity
In
radix_sort::sort, you use member functions begin and end. It is now considered good style to write std::begin and std::end wherever possible so that you won't get into trouble if the code is changed. Moreover, in C++14, you will have std::cbegin and std::cend that rely on member begin and end. That means that pre-C++11 containers that do not provide member cbegin and cend can also be used.Code Snippets
#include <algorithm>
#include <array>
#include <iostream>
#include <numeric>
#include <string>
#include <type_traits>
#include <vector>Context
StackExchange Code Review Q#47069, answer score: 5
Revisions (0)
No revisions yet.