Implementation of Radix Sort algorithm for sorting integers in c++Improving performance when sorting array of...

Is it legal for company to use my work email to pretend I still work there?

What are the differences between the usage of 'it' and 'they'?

Do I have a twin with permutated remainders?

How to add double frame in tcolorbox?

Why, historically, did Gödel think CH was false?

Is it possible to do 50 km distance without any previous training?

What is the word for reserving something for yourself before others do?

The use of multiple foreign keys on same column in SQL Server

Schoenfled Residua test shows proportionality hazard assumptions holds but Kaplan-Meier plots intersect

Unknown notation: What do three bars mean?

Why Is Death Allowed In the Matrix?

Why doesn't H₄O²⁺ exist?

Accidentally leaked the solution to an assignment, what to do now? (I'm the prof)

Why was the small council so happy for Tyrion to become the Master of Coin?

Watching something be written to a file live with tail

Why not use SQL instead of GraphQL?

Smoothness of finite-dimensional functional calculus

Why is Minecraft giving an OpenGL error?

Why does Kotter return in Welcome Back Kotter?

What do the dots in this tr command do: tr .............A-Z A-ZA-Z <<< "JVPQBOV" (with 13 dots)

What does "Puller Prush Person" mean?

Is it tax fraud for an individual to declare non-taxable revenue as taxable income? (US tax laws)

Can a Warlock become Neutral Good?

Have astronauts in space suits ever taken selfies? If so, how?



Implementation of Radix Sort algorithm for sorting integers in c++


Improving performance when sorting array of structs by multiple fieldsSorting millions of integersAdaptive counting sort for integer arrays in JavaExact sort - sorting with few move operationsImplement LSD radix sort in pythonSpaceSort - A new sorting algorithmRadix sort implementationCompare 2 unordered, rooted trees for shape-isomorphismFollow-up 1: Compare 2 unordered, rooted trees for shape-isomorphismC++ - Radix sort implementation






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







3












$begingroup$


I wrote the following code for Radix Sort algorithm for number sorting. Any review is highly appreciated.




You can also view and run/test the code here Radix Sort




#include<iostream>
using namespace std;

int getNumberAtPosition(int num,int position){
return (num/position)%10;
}
void radixSort(int array[],int length){
int sizeOfEachBucket = length;
int numberOfBuckets = 10;
int buckets[10][sizeOfEachBucket];
int large = 0;
int maxPasses = 0;
//finding largest number from array
for(int i=0; i<length; i++){
if(array[i]>large){
large = array[i];
}
}

//finding the number of passes
while(large != 0){
maxPasses++;
large = large/10;
}
cout<<"Max passes ="<<maxPasses<<endl;
int position = 1;
int bucketIndex = 0;
int newListIndex = 0;
int arrayLengths[10];
for(int i=0; i<maxPasses; i++){
//cout<<"i ="<<i<<endl;
for(int k=0; k<=9; k++){
//cout<<"k ="<<k<<endl;
bucketIndex = 0;
for(int j=0; j<length; j++){
if(k==getNumberAtPosition(array[j],position)){
buckets[k][bucketIndex] = array[j];
bucketIndex++;
}
}
arrayLengths[k] = bucketIndex;
}
position = position*10;
int newArrayIndex = 0;
for(int k=0; k<=9; k++){
//cout<<"k ="<<k<<endl;
bucketIndex = 0;
for(int x=0; x<arrayLengths[k];x++){
array[newArrayIndex] = buckets[k][x];
newArrayIndex++;
}
}

}
for(int i=0; i<length; i++){
cout<<array[i]<<"t";
}
}









share|improve this question











$endgroup$



















    3












    $begingroup$


    I wrote the following code for Radix Sort algorithm for number sorting. Any review is highly appreciated.




    You can also view and run/test the code here Radix Sort




    #include<iostream>
    using namespace std;

    int getNumberAtPosition(int num,int position){
    return (num/position)%10;
    }
    void radixSort(int array[],int length){
    int sizeOfEachBucket = length;
    int numberOfBuckets = 10;
    int buckets[10][sizeOfEachBucket];
    int large = 0;
    int maxPasses = 0;
    //finding largest number from array
    for(int i=0; i<length; i++){
    if(array[i]>large){
    large = array[i];
    }
    }

    //finding the number of passes
    while(large != 0){
    maxPasses++;
    large = large/10;
    }
    cout<<"Max passes ="<<maxPasses<<endl;
    int position = 1;
    int bucketIndex = 0;
    int newListIndex = 0;
    int arrayLengths[10];
    for(int i=0; i<maxPasses; i++){
    //cout<<"i ="<<i<<endl;
    for(int k=0; k<=9; k++){
    //cout<<"k ="<<k<<endl;
    bucketIndex = 0;
    for(int j=0; j<length; j++){
    if(k==getNumberAtPosition(array[j],position)){
    buckets[k][bucketIndex] = array[j];
    bucketIndex++;
    }
    }
    arrayLengths[k] = bucketIndex;
    }
    position = position*10;
    int newArrayIndex = 0;
    for(int k=0; k<=9; k++){
    //cout<<"k ="<<k<<endl;
    bucketIndex = 0;
    for(int x=0; x<arrayLengths[k];x++){
    array[newArrayIndex] = buckets[k][x];
    newArrayIndex++;
    }
    }

    }
    for(int i=0; i<length; i++){
    cout<<array[i]<<"t";
    }
    }









    share|improve this question











    $endgroup$















      3












      3








      3





      $begingroup$


      I wrote the following code for Radix Sort algorithm for number sorting. Any review is highly appreciated.




      You can also view and run/test the code here Radix Sort




      #include<iostream>
      using namespace std;

      int getNumberAtPosition(int num,int position){
      return (num/position)%10;
      }
      void radixSort(int array[],int length){
      int sizeOfEachBucket = length;
      int numberOfBuckets = 10;
      int buckets[10][sizeOfEachBucket];
      int large = 0;
      int maxPasses = 0;
      //finding largest number from array
      for(int i=0; i<length; i++){
      if(array[i]>large){
      large = array[i];
      }
      }

      //finding the number of passes
      while(large != 0){
      maxPasses++;
      large = large/10;
      }
      cout<<"Max passes ="<<maxPasses<<endl;
      int position = 1;
      int bucketIndex = 0;
      int newListIndex = 0;
      int arrayLengths[10];
      for(int i=0; i<maxPasses; i++){
      //cout<<"i ="<<i<<endl;
      for(int k=0; k<=9; k++){
      //cout<<"k ="<<k<<endl;
      bucketIndex = 0;
      for(int j=0; j<length; j++){
      if(k==getNumberAtPosition(array[j],position)){
      buckets[k][bucketIndex] = array[j];
      bucketIndex++;
      }
      }
      arrayLengths[k] = bucketIndex;
      }
      position = position*10;
      int newArrayIndex = 0;
      for(int k=0; k<=9; k++){
      //cout<<"k ="<<k<<endl;
      bucketIndex = 0;
      for(int x=0; x<arrayLengths[k];x++){
      array[newArrayIndex] = buckets[k][x];
      newArrayIndex++;
      }
      }

      }
      for(int i=0; i<length; i++){
      cout<<array[i]<<"t";
      }
      }









      share|improve this question











      $endgroup$




      I wrote the following code for Radix Sort algorithm for number sorting. Any review is highly appreciated.




      You can also view and run/test the code here Radix Sort




      #include<iostream>
      using namespace std;

      int getNumberAtPosition(int num,int position){
      return (num/position)%10;
      }
      void radixSort(int array[],int length){
      int sizeOfEachBucket = length;
      int numberOfBuckets = 10;
      int buckets[10][sizeOfEachBucket];
      int large = 0;
      int maxPasses = 0;
      //finding largest number from array
      for(int i=0; i<length; i++){
      if(array[i]>large){
      large = array[i];
      }
      }

      //finding the number of passes
      while(large != 0){
      maxPasses++;
      large = large/10;
      }
      cout<<"Max passes ="<<maxPasses<<endl;
      int position = 1;
      int bucketIndex = 0;
      int newListIndex = 0;
      int arrayLengths[10];
      for(int i=0; i<maxPasses; i++){
      //cout<<"i ="<<i<<endl;
      for(int k=0; k<=9; k++){
      //cout<<"k ="<<k<<endl;
      bucketIndex = 0;
      for(int j=0; j<length; j++){
      if(k==getNumberAtPosition(array[j],position)){
      buckets[k][bucketIndex] = array[j];
      bucketIndex++;
      }
      }
      arrayLengths[k] = bucketIndex;
      }
      position = position*10;
      int newArrayIndex = 0;
      for(int k=0; k<=9; k++){
      //cout<<"k ="<<k<<endl;
      bucketIndex = 0;
      for(int x=0; x<arrayLengths[k];x++){
      array[newArrayIndex] = buckets[k][x];
      newArrayIndex++;
      }
      }

      }
      for(int i=0; i<length; i++){
      cout<<array[i]<<"t";
      }
      }






      c++ algorithm sorting






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Mar 29 at 7:27









      Emma

      1631214




      1631214










      asked Mar 29 at 6:11









      DeepeshkumarDeepeshkumar

      232




      232






















          1 Answer
          1






          active

          oldest

          votes


















          3












          $begingroup$


          • First things first, don't use using namespace std in header files, where your radix sort implementation should be. Besides, convenience isn't a valid excuse when the only thing you import from std is cout: just type std::cout and you're done.


          • One liner functions are often useless and noisy: you need to refer to the implementation to know exactly what they do, so they don't make the code more readable, and you have to come up with a name, which is not always easy. In the case of getNumberAtPosition, for instance, it's impossible to tell from the name if the position is meant for the most or least significant digit, and both are equally likely in a radix sort algorithm.


          • everything that isn't meant to change should be const. The only place where it isn't idiomatic is in function signature, where you often don't tag built-in type arguments passed by value as const.


          • Also, don't alias variables: length is only used to define sizeOfEachBucket, that's two names to track down instead of one.


          • Use the standard library: there may not be many things inside compared to other languages, but what's inside is very well implemented. It will also make your code more concise and expressive. For instance, the largest element in a [first, last) sequence is the result of std::max_element(first, last) (std::max_element resides in <algorithm>). Using standard containers is also a statement: a constant size array will be a std::array, whereas a variable-size one will be a std::vector.


          • Avoid naked loops: by that I mean loops like for (int i = 0; i < z; ++i). The nested ones are particularly difficult to read, with all those meaningless one-letter variable names. Use either range based for loops when you iterate over the whole container (e.g: for (auto item : vector)) or named algorithm when your loop has a standardly implemented purpose (std::for_each, std::copy, etc.).


          • When implementing your own algorithms, try to use an stl-like interface: iterators are preferable because they abstract the concrete container-type. Your algorithm won't work on an std::list although it very well could be (radix sort doesn't rely on random access like quick sort does).



          Here's an example of better-looking (though not thoroughly tested) code:



          #include <algorithm>
          #include <vector>
          #include <array>
          #include <cmath>

          template <typename Iterator>
          void radix_sort(Iterator first, Iterator last) {
          const int max_divisor = std::pow(10, std::log10(*std::max_element(first, last)));
          for (int divisor = 1; divisor < max_divisor; divisor *= 10) {
          std::array<std::vector<int>, 10> buckets;
          std::for_each(first, last, [&buckets, divisor](auto i) {
          buckets[(i / divisor) % 10].push_back(i);
          });
          auto out = first;
          for (const auto& bucket : buckets) {
          out = std::copy(bucket.begin(), bucket.end(), out);
          }
          }
          }


          EDIT: since the algorithm exposed in the question relies on decimal digits, I also formulated a base-10 based algorithm. But thinking back about this, I feel like my answer isn't complete if I don't precise that a base-two approach is more optimal (and more generally used as far as I know). Why is that?




          • because binary arithmetic is easier for a computer (not a very strong reason since decimal arithmetic is often optimized into binary arithmetic by the compiler);


          • because -and that's a much stronger reason- you can the rely on a very well-known algorithm to distribute your number between buckets, an algorithm that moreover does it in place, thus without any memory allocation;


          • by the way, that algorithm is std::stable_partition



          And here is a sample:



          template <typename Iterator>
          void binary_radix_sort(Iterator first, Iterator last) {
          using integer_type = std::decay_t<decltype(*first)>;
          bool finished = false;
          for (integer_type mask = 1; !finished; mask <<= 1) {
          finished = true;
          std::stable_partition(first, last, [mask, &finished](auto i) {
          if (mask < i) finished = false;
          return !(mask & i);
          });
          }
          }





          share|improve this answer











          $endgroup$













          • $begingroup$
            Thanks for such a valuable advice!
            $endgroup$
            – Deepeshkumar
            Mar 29 at 17:34






          • 4




            $begingroup$
            I have to strongly disagree with #2. One line functions often provide important abstractions that are invaluable and significantly reduce cognitive load
            $endgroup$
            – miscco
            Mar 29 at 18:12












          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216460%2fimplementation-of-radix-sort-algorithm-for-sorting-integers-in-c%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          3












          $begingroup$


          • First things first, don't use using namespace std in header files, where your radix sort implementation should be. Besides, convenience isn't a valid excuse when the only thing you import from std is cout: just type std::cout and you're done.


          • One liner functions are often useless and noisy: you need to refer to the implementation to know exactly what they do, so they don't make the code more readable, and you have to come up with a name, which is not always easy. In the case of getNumberAtPosition, for instance, it's impossible to tell from the name if the position is meant for the most or least significant digit, and both are equally likely in a radix sort algorithm.


          • everything that isn't meant to change should be const. The only place where it isn't idiomatic is in function signature, where you often don't tag built-in type arguments passed by value as const.


          • Also, don't alias variables: length is only used to define sizeOfEachBucket, that's two names to track down instead of one.


          • Use the standard library: there may not be many things inside compared to other languages, but what's inside is very well implemented. It will also make your code more concise and expressive. For instance, the largest element in a [first, last) sequence is the result of std::max_element(first, last) (std::max_element resides in <algorithm>). Using standard containers is also a statement: a constant size array will be a std::array, whereas a variable-size one will be a std::vector.


          • Avoid naked loops: by that I mean loops like for (int i = 0; i < z; ++i). The nested ones are particularly difficult to read, with all those meaningless one-letter variable names. Use either range based for loops when you iterate over the whole container (e.g: for (auto item : vector)) or named algorithm when your loop has a standardly implemented purpose (std::for_each, std::copy, etc.).


          • When implementing your own algorithms, try to use an stl-like interface: iterators are preferable because they abstract the concrete container-type. Your algorithm won't work on an std::list although it very well could be (radix sort doesn't rely on random access like quick sort does).



          Here's an example of better-looking (though not thoroughly tested) code:



          #include <algorithm>
          #include <vector>
          #include <array>
          #include <cmath>

          template <typename Iterator>
          void radix_sort(Iterator first, Iterator last) {
          const int max_divisor = std::pow(10, std::log10(*std::max_element(first, last)));
          for (int divisor = 1; divisor < max_divisor; divisor *= 10) {
          std::array<std::vector<int>, 10> buckets;
          std::for_each(first, last, [&buckets, divisor](auto i) {
          buckets[(i / divisor) % 10].push_back(i);
          });
          auto out = first;
          for (const auto& bucket : buckets) {
          out = std::copy(bucket.begin(), bucket.end(), out);
          }
          }
          }


          EDIT: since the algorithm exposed in the question relies on decimal digits, I also formulated a base-10 based algorithm. But thinking back about this, I feel like my answer isn't complete if I don't precise that a base-two approach is more optimal (and more generally used as far as I know). Why is that?




          • because binary arithmetic is easier for a computer (not a very strong reason since decimal arithmetic is often optimized into binary arithmetic by the compiler);


          • because -and that's a much stronger reason- you can the rely on a very well-known algorithm to distribute your number between buckets, an algorithm that moreover does it in place, thus without any memory allocation;


          • by the way, that algorithm is std::stable_partition



          And here is a sample:



          template <typename Iterator>
          void binary_radix_sort(Iterator first, Iterator last) {
          using integer_type = std::decay_t<decltype(*first)>;
          bool finished = false;
          for (integer_type mask = 1; !finished; mask <<= 1) {
          finished = true;
          std::stable_partition(first, last, [mask, &finished](auto i) {
          if (mask < i) finished = false;
          return !(mask & i);
          });
          }
          }





          share|improve this answer











          $endgroup$













          • $begingroup$
            Thanks for such a valuable advice!
            $endgroup$
            – Deepeshkumar
            Mar 29 at 17:34






          • 4




            $begingroup$
            I have to strongly disagree with #2. One line functions often provide important abstractions that are invaluable and significantly reduce cognitive load
            $endgroup$
            – miscco
            Mar 29 at 18:12
















          3












          $begingroup$


          • First things first, don't use using namespace std in header files, where your radix sort implementation should be. Besides, convenience isn't a valid excuse when the only thing you import from std is cout: just type std::cout and you're done.


          • One liner functions are often useless and noisy: you need to refer to the implementation to know exactly what they do, so they don't make the code more readable, and you have to come up with a name, which is not always easy. In the case of getNumberAtPosition, for instance, it's impossible to tell from the name if the position is meant for the most or least significant digit, and both are equally likely in a radix sort algorithm.


          • everything that isn't meant to change should be const. The only place where it isn't idiomatic is in function signature, where you often don't tag built-in type arguments passed by value as const.


          • Also, don't alias variables: length is only used to define sizeOfEachBucket, that's two names to track down instead of one.


          • Use the standard library: there may not be many things inside compared to other languages, but what's inside is very well implemented. It will also make your code more concise and expressive. For instance, the largest element in a [first, last) sequence is the result of std::max_element(first, last) (std::max_element resides in <algorithm>). Using standard containers is also a statement: a constant size array will be a std::array, whereas a variable-size one will be a std::vector.


          • Avoid naked loops: by that I mean loops like for (int i = 0; i < z; ++i). The nested ones are particularly difficult to read, with all those meaningless one-letter variable names. Use either range based for loops when you iterate over the whole container (e.g: for (auto item : vector)) or named algorithm when your loop has a standardly implemented purpose (std::for_each, std::copy, etc.).


          • When implementing your own algorithms, try to use an stl-like interface: iterators are preferable because they abstract the concrete container-type. Your algorithm won't work on an std::list although it very well could be (radix sort doesn't rely on random access like quick sort does).



          Here's an example of better-looking (though not thoroughly tested) code:



          #include <algorithm>
          #include <vector>
          #include <array>
          #include <cmath>

          template <typename Iterator>
          void radix_sort(Iterator first, Iterator last) {
          const int max_divisor = std::pow(10, std::log10(*std::max_element(first, last)));
          for (int divisor = 1; divisor < max_divisor; divisor *= 10) {
          std::array<std::vector<int>, 10> buckets;
          std::for_each(first, last, [&buckets, divisor](auto i) {
          buckets[(i / divisor) % 10].push_back(i);
          });
          auto out = first;
          for (const auto& bucket : buckets) {
          out = std::copy(bucket.begin(), bucket.end(), out);
          }
          }
          }


          EDIT: since the algorithm exposed in the question relies on decimal digits, I also formulated a base-10 based algorithm. But thinking back about this, I feel like my answer isn't complete if I don't precise that a base-two approach is more optimal (and more generally used as far as I know). Why is that?




          • because binary arithmetic is easier for a computer (not a very strong reason since decimal arithmetic is often optimized into binary arithmetic by the compiler);


          • because -and that's a much stronger reason- you can the rely on a very well-known algorithm to distribute your number between buckets, an algorithm that moreover does it in place, thus without any memory allocation;


          • by the way, that algorithm is std::stable_partition



          And here is a sample:



          template <typename Iterator>
          void binary_radix_sort(Iterator first, Iterator last) {
          using integer_type = std::decay_t<decltype(*first)>;
          bool finished = false;
          for (integer_type mask = 1; !finished; mask <<= 1) {
          finished = true;
          std::stable_partition(first, last, [mask, &finished](auto i) {
          if (mask < i) finished = false;
          return !(mask & i);
          });
          }
          }





          share|improve this answer











          $endgroup$













          • $begingroup$
            Thanks for such a valuable advice!
            $endgroup$
            – Deepeshkumar
            Mar 29 at 17:34






          • 4




            $begingroup$
            I have to strongly disagree with #2. One line functions often provide important abstractions that are invaluable and significantly reduce cognitive load
            $endgroup$
            – miscco
            Mar 29 at 18:12














          3












          3








          3





          $begingroup$


          • First things first, don't use using namespace std in header files, where your radix sort implementation should be. Besides, convenience isn't a valid excuse when the only thing you import from std is cout: just type std::cout and you're done.


          • One liner functions are often useless and noisy: you need to refer to the implementation to know exactly what they do, so they don't make the code more readable, and you have to come up with a name, which is not always easy. In the case of getNumberAtPosition, for instance, it's impossible to tell from the name if the position is meant for the most or least significant digit, and both are equally likely in a radix sort algorithm.


          • everything that isn't meant to change should be const. The only place where it isn't idiomatic is in function signature, where you often don't tag built-in type arguments passed by value as const.


          • Also, don't alias variables: length is only used to define sizeOfEachBucket, that's two names to track down instead of one.


          • Use the standard library: there may not be many things inside compared to other languages, but what's inside is very well implemented. It will also make your code more concise and expressive. For instance, the largest element in a [first, last) sequence is the result of std::max_element(first, last) (std::max_element resides in <algorithm>). Using standard containers is also a statement: a constant size array will be a std::array, whereas a variable-size one will be a std::vector.


          • Avoid naked loops: by that I mean loops like for (int i = 0; i < z; ++i). The nested ones are particularly difficult to read, with all those meaningless one-letter variable names. Use either range based for loops when you iterate over the whole container (e.g: for (auto item : vector)) or named algorithm when your loop has a standardly implemented purpose (std::for_each, std::copy, etc.).


          • When implementing your own algorithms, try to use an stl-like interface: iterators are preferable because they abstract the concrete container-type. Your algorithm won't work on an std::list although it very well could be (radix sort doesn't rely on random access like quick sort does).



          Here's an example of better-looking (though not thoroughly tested) code:



          #include <algorithm>
          #include <vector>
          #include <array>
          #include <cmath>

          template <typename Iterator>
          void radix_sort(Iterator first, Iterator last) {
          const int max_divisor = std::pow(10, std::log10(*std::max_element(first, last)));
          for (int divisor = 1; divisor < max_divisor; divisor *= 10) {
          std::array<std::vector<int>, 10> buckets;
          std::for_each(first, last, [&buckets, divisor](auto i) {
          buckets[(i / divisor) % 10].push_back(i);
          });
          auto out = first;
          for (const auto& bucket : buckets) {
          out = std::copy(bucket.begin(), bucket.end(), out);
          }
          }
          }


          EDIT: since the algorithm exposed in the question relies on decimal digits, I also formulated a base-10 based algorithm. But thinking back about this, I feel like my answer isn't complete if I don't precise that a base-two approach is more optimal (and more generally used as far as I know). Why is that?




          • because binary arithmetic is easier for a computer (not a very strong reason since decimal arithmetic is often optimized into binary arithmetic by the compiler);


          • because -and that's a much stronger reason- you can the rely on a very well-known algorithm to distribute your number between buckets, an algorithm that moreover does it in place, thus without any memory allocation;


          • by the way, that algorithm is std::stable_partition



          And here is a sample:



          template <typename Iterator>
          void binary_radix_sort(Iterator first, Iterator last) {
          using integer_type = std::decay_t<decltype(*first)>;
          bool finished = false;
          for (integer_type mask = 1; !finished; mask <<= 1) {
          finished = true;
          std::stable_partition(first, last, [mask, &finished](auto i) {
          if (mask < i) finished = false;
          return !(mask & i);
          });
          }
          }





          share|improve this answer











          $endgroup$




          • First things first, don't use using namespace std in header files, where your radix sort implementation should be. Besides, convenience isn't a valid excuse when the only thing you import from std is cout: just type std::cout and you're done.


          • One liner functions are often useless and noisy: you need to refer to the implementation to know exactly what they do, so they don't make the code more readable, and you have to come up with a name, which is not always easy. In the case of getNumberAtPosition, for instance, it's impossible to tell from the name if the position is meant for the most or least significant digit, and both are equally likely in a radix sort algorithm.


          • everything that isn't meant to change should be const. The only place where it isn't idiomatic is in function signature, where you often don't tag built-in type arguments passed by value as const.


          • Also, don't alias variables: length is only used to define sizeOfEachBucket, that's two names to track down instead of one.


          • Use the standard library: there may not be many things inside compared to other languages, but what's inside is very well implemented. It will also make your code more concise and expressive. For instance, the largest element in a [first, last) sequence is the result of std::max_element(first, last) (std::max_element resides in <algorithm>). Using standard containers is also a statement: a constant size array will be a std::array, whereas a variable-size one will be a std::vector.


          • Avoid naked loops: by that I mean loops like for (int i = 0; i < z; ++i). The nested ones are particularly difficult to read, with all those meaningless one-letter variable names. Use either range based for loops when you iterate over the whole container (e.g: for (auto item : vector)) or named algorithm when your loop has a standardly implemented purpose (std::for_each, std::copy, etc.).


          • When implementing your own algorithms, try to use an stl-like interface: iterators are preferable because they abstract the concrete container-type. Your algorithm won't work on an std::list although it very well could be (radix sort doesn't rely on random access like quick sort does).



          Here's an example of better-looking (though not thoroughly tested) code:



          #include <algorithm>
          #include <vector>
          #include <array>
          #include <cmath>

          template <typename Iterator>
          void radix_sort(Iterator first, Iterator last) {
          const int max_divisor = std::pow(10, std::log10(*std::max_element(first, last)));
          for (int divisor = 1; divisor < max_divisor; divisor *= 10) {
          std::array<std::vector<int>, 10> buckets;
          std::for_each(first, last, [&buckets, divisor](auto i) {
          buckets[(i / divisor) % 10].push_back(i);
          });
          auto out = first;
          for (const auto& bucket : buckets) {
          out = std::copy(bucket.begin(), bucket.end(), out);
          }
          }
          }


          EDIT: since the algorithm exposed in the question relies on decimal digits, I also formulated a base-10 based algorithm. But thinking back about this, I feel like my answer isn't complete if I don't precise that a base-two approach is more optimal (and more generally used as far as I know). Why is that?




          • because binary arithmetic is easier for a computer (not a very strong reason since decimal arithmetic is often optimized into binary arithmetic by the compiler);


          • because -and that's a much stronger reason- you can the rely on a very well-known algorithm to distribute your number between buckets, an algorithm that moreover does it in place, thus without any memory allocation;


          • by the way, that algorithm is std::stable_partition



          And here is a sample:



          template <typename Iterator>
          void binary_radix_sort(Iterator first, Iterator last) {
          using integer_type = std::decay_t<decltype(*first)>;
          bool finished = false;
          for (integer_type mask = 1; !finished; mask <<= 1) {
          finished = true;
          std::stable_partition(first, last, [mask, &finished](auto i) {
          if (mask < i) finished = false;
          return !(mask & i);
          });
          }
          }






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited yesterday

























          answered Mar 29 at 9:27









          papagagapapagaga

          4,787421




          4,787421












          • $begingroup$
            Thanks for such a valuable advice!
            $endgroup$
            – Deepeshkumar
            Mar 29 at 17:34






          • 4




            $begingroup$
            I have to strongly disagree with #2. One line functions often provide important abstractions that are invaluable and significantly reduce cognitive load
            $endgroup$
            – miscco
            Mar 29 at 18:12


















          • $begingroup$
            Thanks for such a valuable advice!
            $endgroup$
            – Deepeshkumar
            Mar 29 at 17:34






          • 4




            $begingroup$
            I have to strongly disagree with #2. One line functions often provide important abstractions that are invaluable and significantly reduce cognitive load
            $endgroup$
            – miscco
            Mar 29 at 18:12
















          $begingroup$
          Thanks for such a valuable advice!
          $endgroup$
          – Deepeshkumar
          Mar 29 at 17:34




          $begingroup$
          Thanks for such a valuable advice!
          $endgroup$
          – Deepeshkumar
          Mar 29 at 17:34




          4




          4




          $begingroup$
          I have to strongly disagree with #2. One line functions often provide important abstractions that are invaluable and significantly reduce cognitive load
          $endgroup$
          – miscco
          Mar 29 at 18:12




          $begingroup$
          I have to strongly disagree with #2. One line functions often provide important abstractions that are invaluable and significantly reduce cognitive load
          $endgroup$
          – miscco
          Mar 29 at 18:12


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f216460%2fimplementation-of-radix-sort-algorithm-for-sorting-integers-in-c%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          is 'sed' thread safeWhat should someone know about using Python scripts in the shell?Nexenta bash script uses...

          How do i solve the “ No module named 'mlxtend' ” issue on Jupyter?

          Pilgersdorf Inhaltsverzeichnis Geografie | Geschichte | Bevölkerungsentwicklung | Politik | Kultur...