C++ - Radix sort implementation
A vector is usually the best data structure to use unless you have a compelling reason to use something else.  Since you know how many buckets you need, one slight improvement you can make to your buckets is to use an array of vectors, rather than a vector of vectors:

std::array&lt;std::vector&lt;int&gt;, 10&gt; buckets;


This will create 10 empty vectors on the stack (without dynamically allocating those 10).

To find the largest element in an unsorted container requires looking at every element in the container.  The only way to improve on that is to change your algorithm so that it does not need to know what the maximum element is; more on that below.

There are several issues with your sort.  In its current form, it does not handle the trivial case of an empty arr as your scan for a maximum element will dereference the end iterator which is not allowed.  Nor does it does it handle negative numbers.  The % operator can return negative numbers if the numerator is negative.  This will result in an out-of-bounds array element access.  There will also be problems with really large numbers (greater than std::numeric_limits&lt;int&gt;::max() / 10).

One way to handle negative numbers is to make an initial pass where you split the array to sort into two groups, one with negative numbers and the other with non-negative numbers.  Then you can radix sort each group, taking care when doing the negative numbers to keep the intermediate results properly signed.

Failing that, how can you determine when to end your loop if you don't know what the maximum element is?  You can keep track as you put things into buckets.  When the num / radix calculation is 0, that element will always be placed in the first (0) bucket for the rest of the sort.  There may be a larger element earlier in the bucket (think of sorting {203, 3}) so it might still move.  But once all elements have that term 0 then you can stop sorting.

When moving the elements out of the buckets back into the array, you can use the standard algorithms rather than using your nested for loops.  The buckets[i].size() will potentially be calculated every iteration.  You can use std::copy to transfer the elements:

auto k = arr.begin();
for (auto &amp;b: buckets)
    k = std::copy(b.begin(), b.end(), k);


You should pass the parameter to print_arr as a const &amp;  (print_arr(const std::vector&lt;int&gt; &amp;arr)).