HiveBrain v1.2.0
Get Started
← Back to all entries
snippetcppMinor

Generic radix sort

Submitted by: @import:stackexchange-codereview··
0
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 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:

#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.