Sorting algorithms/Radix sort

From Rosetta Code
Revision as of 06:53, 15 March 2015 by rosettacode>Gerard Schildberger (→‎{{header|REXX}}: removed OVERFLOW from the STYLE html tag in PRE.)
Task
Sorting algorithms/Radix sort
You are encouraged to solve this task according to the task description, using any language you may know.

In this task, the goal is to sort an integer array with the radix sort algorithm. The primary purpose is to complete the characterization of sort algorithms task.

Ada

radix_sort.adb: <lang Ada>with Ada.Text_IO; procedure Radix_Sort is

  type Integer_Array is array (Positive range <>) of Integer;
  procedure Least_Significant_Radix_Sort (Data : in out Integer_Array; Base : Positive := 10) is
     type Bucket is record
        Count   : Natural := 0;
        Content : Integer_Array (Data'Range);
     end record;
     subtype Bucket_Index is Integer range -Base + 1 .. Base - 1;
     type Bucket_Array is array (Bucket_Index) of Bucket;
     procedure Append (To : in out Bucket; Item : Integer) is
     begin
        To.Count := To.Count + 1;
        To.Content (To.Count) := Item;
     end Append;
     function Get_Nth_Digit (Value : Integer; N : Positive) return Integer is
        Result : Integer := (Value / (Base ** (N - 1))) mod Base;
     begin
        if Value < 0 then
           Result := -Result;
        end if;
        return Result;
     end Get_Nth_Digit;
     function Get_Maximum return Natural is
        Result : Natural := 0;
     begin
        for I in Data'Range loop
           if abs (Data (I)) > Result then
              Result := abs (Data (I));
           end if;
        end loop;
        return Result;
     end Get_Maximum;
     function Split (Pass : Positive) return Bucket_Array is
        Buckets : Bucket_Array;
     begin
        for I in Data'Range loop
           Append (To   => Buckets (Get_Nth_Digit (Data (I), Pass)),
                   Item => Data (I));
        end loop;
        return Buckets;
     end Split;
     function Merge (Buckets : Bucket_Array) return Integer_Array is
        Result        : Integer_Array (Data'Range);
        Current_Index : Positive := 1;
     begin
        for Sublist in Buckets'Range loop
           for Item in 1 .. Buckets (Sublist).Count loop
              Result (Current_Index) := Buckets (Sublist).Content (Item);
              Current_Index := Current_Index + 1;
           end loop;
        end loop;
        return Result;
     end Merge;
     Max_Number  : Natural := Get_Maximum;
     Digit_Count : Positive := 1;
  begin
     -- count digits of biggest number
     while Max_Number > Base loop
        Digit_Count := Digit_Count + 1;
        Max_Number := Max_Number / Base;
     end loop;
     for Pass in 1 .. Digit_Count loop
        Data := Merge (Split (Pass));
     end loop;
  end Least_Significant_Radix_Sort;
  Test_Array : Integer_Array := (170, 45, 75, -90, -802, 24, 2, 66);

begin

  Least_Significant_Radix_Sort (Test_Array, 4);
  for I in Test_Array'Range loop
     Ada.Text_IO.Put (Integer'Image (Test_Array (I)));
  end loop;
  Ada.Text_IO.New_Line;

end Radix_Sort;</lang>

output:

-802-90 2 24 45 66 75 170

AutoHotkey

<lang AutoHotkey>Radix_Sort(data){ loop, parse, data, `, n := StrLen(A_LoopField)>n?StrLen(A_LoopField):n loop % n { bucket := [] , i := A_Index loop, parse, data, `, bucket[SubStr(A_LoopField,1-i)] .= (bucket[SubStr(A_LoopField,1-i)]?",":"") A_LoopField data := "" for i, v in bucket data .= (data?",":"") v } return data }</lang> Examples:<lang AutoHotkey>d = 170,45,75,90,802,2,24,66 MsgBox, 262144, , % Radix_Sort(d)</lang>

Outputs:

2,24,45,66,75,90,170,802

BBC BASIC

The array index is assumed to start at zero. The third parameter of PROCradixsort() is the radix used. <lang bbcbasic> DIM test%(9)

     test%() = 4, 65, 2, -31, 0, 99, 2, 83, 782, 1
     PROCradixsort(test%(), 10, 10)
     FOR i% = 0 TO 9
       PRINT test%(i%) ;
     NEXT
     PRINT
     END
     
     DEF PROCradixsort(a%(), n%, r%)
     LOCAL d%, e%, i%, l%, m%, b%(), bucket%()
     DIM b%(n%-1), bucket%(r%-1)
     FOR i% = 0 TO n%-1
       IF a%(i%) < l% l% = a%(i%)
       IF a%(i%) > m% m% = a%(i%)
     NEXT
     a%() -= l%
     m% -= l%
     e% = 1
     WHILE m% DIV e%
       bucket%() = 0
       FOR i% = 0 TO n%-1
         bucket%(a%(i%) DIV e% MOD r%) += 1
       NEXT
       FOR i% = 1 TO r%-1
         bucket%(i%) += bucket%(i% - 1)
       NEXT
       FOR i% = n%-1 TO 0 STEP -1
         d% = a%(i%) DIV e% MOD r%
         bucket%(d%) -= 1
         b%(bucket%(d%)) = a%(i%)
       NEXT
       a%() = b%()
       e% *= r%
     ENDWHILE
     a%() += l%
     ENDPROC</lang>

Output:

       -31         0         1         2         2         4        65        83        99       782

C

Radix sort, "digits" are most significant bits.<lang c>#include <stdio.h>

  1. include <limits.h>
  2. include <stdlib.h>

typedef unsigned uint;

  1. define swap(a, b) { tmp = a; a = b; b = tmp; }
  2. define each(i, x) for (i = 0; i < x; i++)

/* sort unsigned ints */ static void rad_sort_u(uint *from, uint *to, uint bit) { if (!bit || to < from + 1) return;

uint *ll = from, *rr = to - 1, tmp; while (1) { /* find left most with bit, and right most without bit, swap */ while (ll < rr && !(*ll & bit)) ll++; while (ll < rr && (*rr & bit)) rr--; if (ll >= rr) break; swap(*ll, *rr); }

if (!(bit & *ll) && ll < to) ll++; bit >>= 1;

rad_sort_u(from, ll, bit); rad_sort_u(ll, to, bit); }

/* sort signed ints: flip highest bit, sort as unsigned, flip back */ static void radix_sort(int *a, const size_t len) { size_t i; uint *x = (uint*) a;

each(i, len) x[i] ^= INT_MIN; rad_sort_u(x, x + len, INT_MIN); each(i, len) x[i] ^= INT_MIN; }

static inline void radix_sort_unsigned(uint *a, const size_t len) { rad_sort_u(a, a + len, (uint)INT_MIN); }

int main(void) { int len = 16, x[16], i; size_t len = 16, i; each(i, len) x[i] = rand() % 512 - 256;

radix_sort(x, len);

each(i, len) printf("%d%c", x[i], i + 1 < len ? ' ' : '\n');

return 0;

}</lang>output

-182 -175 -151 -141 -70 -51 -20 -5 -1 41 70 103 171 198 227 242

C++

Implements a least significant digit radix sort and a recursive most significant digit radix sort.

Note: the LSD radix sort uses the standard library std::stable_partition algorithm. This algorithm is guaranteed to preserve relative order and has a higher runtime cost. The MSD radix sort uses std::partition and can be significantly faster. <lang cpp>#include <algorithm>

  1. include <iostream>
  2. include <iterator>

// Radix sort comparator for 32-bit two's complement integers class radix_test {

   const int bit; // bit position [0..31] to examine

public:

   radix_test(int offset) : bit(offset) {} // constructor
   bool operator()(int value) const // function call operator
   {
       if (bit == 31) // sign bit
           return value < 0; // negative int to left partition
       else
           return !(value & (1 << bit)); // 0 bit to left partition
   }

};

// Least significant digit radix sort void lsd_radix_sort(int *first, int *last) {

   for (int lsb = 0; lsb < 32; ++lsb) // least-significant-bit
   {
       std::stable_partition(first, last, radix_test(lsb));
   }

}

// Most significant digit radix sort (recursive) void msd_radix_sort(int *first, int *last, int msb = 31) {

   if (first != last && msb >= 0)
   {
       int *mid = std::partition(first, last, radix_test(msb));
       msb--; // decrement most-significant-bit
       msd_radix_sort(first, mid, msb); // sort left partition
       msd_radix_sort(mid, last, msb); // sort right partition
   }

}

// test radix_sort int main() {

   int data[] = { 170, 45, 75, -90, -802, 24, 2, 66 };
   lsd_radix_sort(data, data + 8);
   // msd_radix_sort(data, data + 8);
   std::copy(data, data + 8, std::ostream_iterator<int>(std::cout, " "));
   return 0;

}</lang> Output:

-802 -90 2 24 45 66 75 170 

C#

Works with: C# version 3.0+

<lang csharp>using System;

namespace RadixSort {

   class Program
   {
       static void Sort(int[] old)
       {
           int i, j;
           int[] tmp = new int[old.Length];
           for (int shift = 31; shift > -1; --shift)
           {
               j = 0;
               for (i = 0; i < old.Length; ++i)
               {
                   bool move = (old[i] << shift) >= 0;
                   if (shift == 0 ? !move : move)  // shift the 0's to old's head
                       old[i-j] = old[i];
                   else                            // move the 1's to tmp
                       tmp[j++] = old[i];
               }
               Array.Copy(tmp, 0, old, old.Length-j, j);
           }
       }
       static void Main(string[] args)
       {
           int[] old = new int[] { 2, 5, 1, -3, 4 };
           Console.WriteLine(string.Join(", ", old));
           Sort(old);
           Console.WriteLine(string.Join(", ", old));
           Console.Read();
       }
   }

}</lang>

D

Shorter Version

<lang d>import std.stdio, std.math, std.traits, std.range, std.algorithm;

ElementType!R[] radixSort(size_t N=10, R)(R r) if (hasLength!R && isRandomAccessRange!R &&

   isIntegral!(ElementType!R)) {
   alias ElementType!R E;
   static if (isDynamicArray!R)
       alias r res;         // input is array => in place sort
   else
       E[] res = r.array(); // input is Range => return a new array
   E absMax = r.map!abs().reduce!max();
   immutable nPasses = 1 + cast(int)(log(absMax) / log(N));
   foreach (pass; 0 .. nPasses) {
       auto bucket = new E[][](2 * N - 1, 0);
       foreach (v; res) {
           int bIdx = abs(v / (N ^^ pass)) % N;
           bIdx = (v < 0) ? -bIdx : bIdx;
           bucket[N + bIdx - 1] ~= v;
       }
       res = bucket.join();
   }
   return res;

}

void main() {

   auto items = [170, 45, 75, -90, 2, 24, -802, 66];
   items.radixSort().writeln();
   items.map!q{1 - a}().radixSort().writeln();

}</lang>

Output:
[-802, -90, 2, 24, 45, 66, 75, 170]
[-1, -23, -44, -65, -74, -169, 91, 803]

More Efficient Version

<lang d>import std.array, std.traits;

// considered pure for this program extern(C) void* alloca(in size_t length) pure nothrow;

void radixSort(size_t MAX_ALLOCA=5_000, U)(U[] data) pure nothrow if (isUnsigned!U) {

   static void radix(in uint byteIndex, in U[] source, U[] dest)
   pure nothrow {
       immutable size_t sourceSize = source.length;
       ubyte* curByte = (cast(ubyte*)source.ptr) + byteIndex;
       uint[ubyte.max + 1] byteCounter;
       for (size_t i = 0; i < sourceSize; i++, curByte += U.sizeof)
           byteCounter[*curByte]++;
       {
           uint indexStart;
           foreach (uint i; 0 .. byteCounter.length) {
               immutable size_t tempCount = byteCounter[i];
               byteCounter[i] = indexStart;
               indexStart += tempCount;
           }
       }
       curByte = (cast(ubyte*)source.ptr) + byteIndex;
       for (size_t i = 0; i < sourceSize; i++, curByte += U.sizeof) {
           uint* countPtr = byteCounter.ptr + *curByte;
           dest[*countPtr] = source[i];
           (*countPtr)++;
       }
   }
   U[] tempData;
   if (U.sizeof * data.length <= MAX_ALLOCA) {
       U* ptr = cast(U*)alloca(data.length * U.sizeof);
       if (ptr != null)
           tempData = ptr[0 .. data.length];
   }
   if (tempData.empty)
       tempData = uninitializedArray!(U[])(data.length);
   static if (U.sizeof == 1) {
       radix(0, data, tempData);
       data[] = tempData[];
   } else {
       for (uint i = 0; i < U.sizeof; i += 2) {
           radix(i + 0, data, tempData);
           radix(i + 1, tempData, data);
       }
   }

}

void main() {

   import std.stdio;
   uint[] items = [170, 45, 75, 4294967206, 2, 24, 4294966494, 66];
   items.radixSort();
   writeln(items);

}</lang>

Output:
[2, 24, 45, 66, 75, 170, 4294966494, 4294967206]

Original C++ code, modified (unknown license), by Andre Reinald, Paul Harris, Ryan Rohrer, Dirk Jagdmann: http://www.cubic.org/docs/download/radix_ar_2011.cpp

Go

LSD radix 256, negatives handled by flipping the high bit. <lang go>package main

import (

   "bytes"
   "encoding/binary"
   "fmt"

)

// declarations for word size of data type word int32 const wordLen = 4 const highBit = -1 << 31

var data = []word{170, 45, 75, -90, -802, 24, 2, 66}

func main() {

   buf := bytes.NewBuffer(nil)
   ds := make([][]byte, len(data))
   for i, x := range data {
       binary.Write(buf, binary.LittleEndian, x^highBit)
       b := make([]byte, wordLen)
       buf.Read(b)
       ds[i] = b
   }
   bins := make([][][]byte, 256)
   for i := 0; i < wordLen; i++ {
       for _, b := range ds {
           bins[b[i]] = append(bins[b[i]], b)
       }
       j := 0
       for k, bs := range bins {
           copy(ds[j:], bs)
           j += len(bs)
           bins[k] = bs[:0]
       }
   }
   fmt.Println("original:", data)
   var w word
   for i, b := range ds {
       buf.Write(b)
       binary.Read(buf, binary.LittleEndian, &w)
       data[i] = w^highBit
   }
   fmt.Println("sorted:  ", data)

}</lang> Output:

original: [170 45 75 -90 -802 24 2 66]
sorted:   [-802 -90 2 24 45 66 75 170]

Groovy

This solution assumes the radix is a power of 2: <lang groovy>def radixSort = { final radixExponent, list ->

   def fromBuckets = new TreeMap([0:list])
   def toBuckets = new TreeMap()
   final radix = 2**radixExponent
   final mask = radix - 1
   final radixDigitSize = (int)Math.ceil(64/radixExponent)
   final digitWidth = radixExponent
   (0..<radixDigitSize).each { radixDigit ->
       fromBuckets.values().findAll { it != null }.flatten().each {
           print '.'
           long bucketNumber = (long)((((long)it) >>> digitWidth*radixDigit) & mask)
           toBuckets[bucketNumber] = toBuckets[bucketNumber] ?: []
           toBuckets[bucketNumber] << it
       }
       (fromBuckets, toBuckets) = [toBuckets, fromBuckets]
       toBuckets.clear()
   }
   final overflow = 2**(63 % radixExponent)
   final pos = {it < overflow}
   final neg = {it >= overflow}
   final keys = fromBuckets.keySet()
   final twosComplIndx = [] + (keys.findAll(neg)) + (keys.findAll(pos))
   twosComplIndx.collect { fromBuckets[it] }.findAll { it != null }.flatten()

}</lang>

Test: <lang groovy>println (radixSort(3, [23,76,99,58,97,57,35,89,51,38,95,92,24,46,31,24,14,12,57,78,4])) println (radixSort(3, [88,18,31,44,4,0,8,81,14,78,20,76,84,33,73,75,82,5,62,70,12,7,1])) println (radixSort(3, [23,-76,-990,580,97,57,350000,Long.MAX_VALUE,89,Long.MIN_VALUE,51,38,95*2**48,92,-24*2**48,46,31*2**32,24,14,12,57,78,4])) println () println (radixSort(8, [23,76,99,58,97,57,35,89,51,38,95,92,24,46,31,24,14,12,57,78,4])) println (radixSort(8, [88,18,31,44,4,0,8,81,14,78,20,76,84,33,73,75,82,5,62,70,12,7,1])) println (radixSort(8, [23,-76,-990,580,97,57,350000,Long.MAX_VALUE,89,Long.MIN_VALUE,51,38,95*2**48,92,-24*2**48,46,31*2**32,24,14,12,57,78,4])) println () println (radixSort(11, [23,76,99,58,97,57,35,89,51,38,95,92,24,46,31,24,14,12,57,78,4])) println (radixSort(11, [88,18,31,44,4,0,8,81,14,78,20,76,84,33,73,75,82,5,62,70,12,7,1])) println (radixSort(11, [23,-76,-990,580,97,57,350000,Long.MAX_VALUE,89,Long.MIN_VALUE,51,38,95*2**48,92,-24*2**48,46,31*2**32,24,14,12,57,78,4])) println () println (radixSort(16, [23,76,99,58,97,57,35,89,51,38,95,92,24,46,31,24,14,12,57,78,4])) println (radixSort(16, [88,18,31,44,4,0,8,81,14,78,20,76,84,33,73,75,82,5,62,70,12,7,1])) println (radixSort(16, [23,-76,-990,580,97,57,350000,Long.MAX_VALUE,89,Long.MIN_VALUE,51,38,95*2**48,92,-24*2**48,46,31*2**32,24,14,12,57,78,4])) println () println (radixSort(32, [23,76,99,58,97,57,35,89,51,38,95,92,24,46,31,24,14,12,57,78,4])) println (radixSort(32, [88,18,31,44,4,0,8,81,14,78,20,76,84,33,73,75,82,5,62,70,12,7,1])) println (radixSort(32, [23,-76,-990,580,97,57,350000,Long.MAX_VALUE,89,Long.MIN_VALUE,51,38,95*2**48,92,-24*2**48,46,31*2**32,24,14,12,57,78,4]))</lang>

Output:

..............................................................................................................................................................................................................................................................................................................................................................................................................................................................................[4, 12, 14, 23, 24, 24, 31, 35, 38, 46, 51, 57, 57, 58, 76, 78, 89, 92, 95, 97, 99]
..........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................[0, 1, 4, 5, 7, 8, 12, 14, 18, 20, 31, 33, 44, 62, 70, 73, 75, 76, 78, 81, 82, 84, 88]
..........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................[-9223372036854775808, -6755399441055744, -990, -76, 4, 12, 14, 23, 24, 38, 46, 51, 57, 57, 78, 89, 92, 97, 580, 350000, 133143986176, 26740122787512320, 9223372036854775807]

........................................................................................................................................................................[4, 12, 14, 23, 24, 24, 31, 35, 38, 46, 51, 57, 57, 58, 76, 78, 89, 92, 95, 97, 99]
........................................................................................................................................................................................[0, 1, 4, 5, 7, 8, 12, 14, 18, 20, 31, 33, 44, 62, 70, 73, 75, 76, 78, 81, 82, 84, 88]
........................................................................................................................................................................................[-9223372036854775808, -6755399441055744, -990, -76, 4, 12, 14, 23, 24, 38, 46, 51, 57, 57, 78, 89, 92, 97, 580, 350000, 133143986176, 26740122787512320, 9223372036854775807]

..............................................................................................................................[4, 12, 14, 23, 24, 24, 31, 35, 38, 46, 51, 57, 57, 58, 76, 78, 89, 92, 95, 97, 99]
..........................................................................................................................................[0, 1, 4, 5, 7, 8, 12, 14, 18, 20, 31, 33, 44, 62, 70, 73, 75, 76, 78, 81, 82, 84, 88]
..........................................................................................................................................[-9223372036854775808, -6755399441055744, -990, -76, 4, 12, 14, 23, 24, 38, 46, 51, 57, 57, 78, 89, 92, 97, 580, 350000, 133143986176, 26740122787512320, 9223372036854775807]

....................................................................................[4, 12, 14, 23, 24, 24, 31, 35, 38, 46, 51, 57, 57, 58, 76, 78, 89, 92, 95, 97, 99]
............................................................................................[0, 1, 4, 5, 7, 8, 12, 14, 18, 20, 31, 33, 44, 62, 70, 73, 75, 76, 78, 81, 82, 84, 88]
............................................................................................[-9223372036854775808, -6755399441055744, -990, -76, 4, 12, 14, 23, 24, 38, 46, 51, 57, 57, 78, 89, 92, 97, 580, 350000, 133143986176, 26740122787512320, 9223372036854775807]

..........................................[4, 12, 14, 23, 24, 24, 31, 35, 38, 46, 51, 57, 57, 58, 76, 78, 89, 92, 95, 97, 99]
..............................................[0, 1, 4, 5, 7, 8, 12, 14, 18, 20, 31, 33, 44, 62, 70, 73, 75, 76, 78, 81, 82, 84, 88]
..............................................[-9223372036854775808, -6755399441055744, -990, -76, 4, 12, 14, 23, 24, 38, 46, 51, 57, 57, 78, 89, 92, 97, 580, 350000, 133143986176, 26740122787512320, 9223372036854775807]

Haskell

<lang haskell>import Data.Bits (Bits(testBit, bitSize)) import Data.List (partition)

lsdSort :: (Ord a, Bits a) => [a] -> [a] lsdSort = fixSort positiveLsdSort

msdSort :: (Ord a, Bits a) => [a] -> [a] msdSort = fixSort positiveMsdSort

-- Fix a sort that puts negative numbers at the end, like positiveLsdSort and positiveMsdSort fixSort sorter list = uncurry (flip (++)) (break (< 0) (sorter list))

positiveLsdSort :: (Bits a) => [a] -> [a] positiveLsdSort list = foldl step list [0..bitSize (head list)] where step list bit = uncurry (++) (partition (not . flip testBit bit) list)

positiveMsdSort :: (Bits a) => [a] -> [a] positiveMsdSort list = aux (bitSize (head list) - 1) list where aux _ [] = [] aux (-1) list = list aux bit list = aux (bit - 1) lower ++ aux (bit - 1) upper where (lower, upper) = partition (not . flip testBit bit) list</lang>

Icon and Unicon

The following is nice and short and works in both languages. However it contains a subtle inefficiency: subscripting a numeric value first coerces it into a string.

<lang unicon>procedure main(A)

   every writes((!rSort(A)||" ")|"\n")

end

procedure rSort(A)

   every (min := A[1]) >:= !A
   every (mlen := *(A[1]-min)) <:= (!A - min)
   every i := !*mlen do {
       every put(b := [], |[]\12)
       every a := !A do put(b[(a-min)[-i]+2|1], a)
       every put(A := [],!!b)
       }
   return A

end</lang>

Sample run:

->radix 31 123 -98 7090 802 2
-98 2 31 123 802 7090
->

J

Generally, this task should be accomplished in J using /:~. Here we take an approach that's more comparable with the other examples on this page.

keys f/. data evaluates the function f on each group of data at the same position as similar keys. Sorting requires ordered keys. This code uses a J idiom: prepend the keys and matching data. The extra data is removed by behead }..

<lang j> radixSortR =: 3 : 0 NB. base radixSort data 16 radixSortR y

keys =. x #.^:_1 y NB. compute keys length =. #{.keys extra =. (-length) {."0 buckets =. i.x for_pass. i.-length do.

  keys =. ; (buckets,pass{"1 keys) <@:}./.extra,keys

end. x#.keys NB. restore the data )</lang>

An alternate implementation is <lang j>radixsort=: (] #~ [: +/ =/) i.@(>./)</lang>

This uses the maximum value of the list for the base, which allows the list to be sorted in one pass.

Example use:

<lang j> radixsort ?.@#~10 4 5 6 6 6 6 6 8 8</lang>

Or, for negative number support:

<lang j>rsort=: (] + radixsort@:-) <./</lang>

Example:

<lang j> rsort _6+?.@#~10 _2 _1 0 0 0 0 0 2 2</lang>

Java

<lang java>public static int[] sort(int[] old) {

   // Loop for every bit in the integers
   for (int shift = Integer.SIZE - 1; shift > -1; shift--) {
       // The array to put the partially sorted array into
       int[] tmp = new int[old.length];
       // The number of 0s
       int j = 0;
       // Move the 0s to the new array, and the 1s to the old one
       for (int i = 0; i < old.length; i++) {
           // If there is a 1 in the bit we are testing, the number will be negative
           boolean move = old[i] << shift >= 0;
           // If this is the last bit, negative numbers are actually lower
           if (shift == 0 ? !move : move) {
               tmp[j] = old[i];
               j++;
           } else {
               // It's a 1, so stick it in the old array for now
               old[i - j] = old[i];
           }
       }
       // Copy over the 1s from the old array
       for (int i = j; i < tmp.length; i++) {
           tmp[i] = old[i - j];
       }
       // And now the tmp array gets switched for another round of sorting
       old = tmp;
   }
   return old;

}</lang>

Translation of: NetRexx

<lang Java> import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Queue;

public class RSortingRadixsort00 {

 public RSortingRadixsort00() {
   return;
 }
 public static int[] lsdRadixSort(int[] tlist) {
   List<Integer> intermediates;
   int[] limits = getLimits(tlist);
   tlist = rescale(tlist, limits[1]);
   for (int px = 1; px <= limits[2]; ++px) {
     @SuppressWarnings("unchecked")
     Queue<Integer> bukits[] = new Queue[10];
     for (int ix = 0; ix < tlist.length; ++ix) {
       int cval = tlist[ix];
       int digit = (int) (cval / Math.pow(10, px - 1) % 10);
       if (bukits[digit] == null) {
         bukits[digit] = new LinkedList<>();
       }
       bukits[digit].add(cval);
     }
     intermediates = new ArrayList<>();
     for (int bi = 0; bi < 10; ++bi) {
       if (bukits[bi] != null) {
         while (bukits[bi].size() > 0) {
           int nextd;
           nextd = bukits[bi].poll();
           intermediates.add(nextd);
         }
       }
     }
     for (int iw = 0; iw < intermediates.size(); ++iw) {
       tlist[iw] = intermediates.get(iw);
     }
   }
   tlist = rescale(tlist, -limits[1]);
   return tlist;
 }
 private static int[] rescale(int[] arry, int delta) {
   for (int ix = 0; ix < arry.length; ++ix) {
     arry[ix] -= delta;
   }
   return arry;
 }
 private static int[] getLimits(int[] tlist) {
   int[] lims = new int[3];
   for (int i_ = 0; i_ < tlist.length; ++i_) {
     lims[0] = Math.max(lims[0], tlist[i_]);
     lims[1] = Math.min(lims[1], tlist[i_]);
   }
   lims[2] = (int) Math.ceil(Math.log10(lims[0] - lims[1]));
   return lims;
 }
 private static void runSample(String[] args) {
   int[][] lists = {
     new int[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, },
     new int[] { -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, -0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, },
     new int[] { 2, 24, 45, 0, 66, 75, 170, -802, -90, 1066, 666, },
     new int[] { 170, 45, 75, 90, 2, 24, 802, 66, },
     new int[] { -170, -45, -75, -90, -2, -24, -802, -66, },
   };
   long etime;
   lsdRadixSort(Arrays.copyOf(lists[0], lists[0].length)); // do one pass to set up environment to remove it from timings
   for (int[] tlist : lists) {
     System.out.println(array2list(tlist));
     etime = System.nanoTime();
     tlist = lsdRadixSort(tlist);
     etime = System.nanoTime() - etime;
     System.out.println(array2list(tlist));
     System.out.printf("Elapsed time: %fs%n", ((double) etime / 1_000_000_000.0));
     System.out.println();
   }
   return;
 }
 private static List<Integer> array2list(int[] arry) {
   List<Integer> target = new ArrayList<>(arry.length);
   for (Integer iv : arry) {
     target.add(iv);
   }
   return target;
 }
 public static void main(String[] args) {
   runSample(args);
   return;
 }

} </lang>

Output:
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]
[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Elapsed time: 0.000256s

[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Elapsed time: 0.000198s

[2, 24, 45, 0, 66, 75, 170, -802, -90, 1066, 666]
[-802, -90, 0, 2, 24, 45, 66, 75, 170, 666, 1066]
Elapsed time: 0.000187s

[170, 45, 75, 90, 2, 24, 802, 66]
[2, 24, 45, 66, 75, 90, 170, 802]
Elapsed time: 0.000088s

[-170, -45, -75, -90, -2, -24, -802, -66]
[-802, -170, -90, -75, -66, -45, -24, -2]
Elapsed time: 0.000113s

jq

<lang jq># Sort the input array;

  1. "base" must be an integer greater than 1

def radix_sort(base):

 # We only need the ceiling of non-negatives:
 def ceil: if . == floor then . else (. + 1 | floor) end;
 min as $min
 | map(. - $min)
 | ((( max|log) / (base|log)) | ceil) as $rounds
 | reduce range(0; $rounds) as $i
     # state: [ base^i, buckets ]
     ( [1, .];
       .[0] as $base_i
       | reduce .[1][] as $n 
           ([];
            (($n/$base_i) % base) as $digit
            | .[$digit] += [$n] )
       | [($base_i * base), (map(select(. != null)) | flatten)] )
 | .[1]
 | map(. + $min) ;

def radix_sort:

 radix_sort(10);

</lang> Example <lang jq>

  1. Verify that radix_sort agrees with sort

( [1, 3, 8, 9, 0, 0, 8, 7, 1, 6],

 [170, 45, 75, 90, 2, 24, 802, 66],
 [170, 45, 75, 90, 2, 24, -802, -66] ) 

| (radix_sort == sort) </lang>

Output:
true
true
true

Mathematica

<lang Mathematica>ClearAll[SortByPos, RadixSort] SortByPos[data : {_List ..}, pos_Integer] := Module[{digs, order},

 digs = dataAll, pos;
 order = Ordering[digs];
 dataorder
 ]

RadixSort[x : {_Integer ..}] := Module[{y, digs, maxlen, offset},

 offset = Min[x];
 y = x - offset;
 digs = IntegerDigits /@ y;
 maxlen = Max[Length /@ digs];
 digs = IntegerDigits[#, 10, maxlen] & /@ y;
 digs = Fold[SortByPos, digs, -Range[maxlen]];
 digs = FromDigits /@ digs;
 digs += offset;
 digs
 ]</lang>

Testing out the algorithm: <lang Mathematica>RadixSort[{170,45,75,-90,-802,24,2,66}] RadixSort[{170,45,75,90,802,2,24,66}]</lang>

Output:
{-802,-90,2,24,45,66,75,170}
{2,24,45,66,75,90,170,802}


NetRexx

Uses a suggestion in the discussion page to handle negative values.
Limitations - Handles decimal digits only.

Using the Rexx class

<lang NetRexx>/* NetRexx */ options replace format comments java crossref symbols nobinary

runSample(arg) return

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method radixSort(tlist = Rexx[]) public static returns Rexx[]

 -- scale the array to start at zero to allow handling of -ve values
 parse getLimits(tlist) maxn minn maxl .
 tlist = rescale(tlist, minn)
 loop px = maxl to 1 by -1
   bukits = 
   loop ix = 0 to tlist.length - 1
     cval = tlist[ix].right(maxl, 0)
     parse cval . =(px) digit +1 .
     bukits[digit] = bukits[digit] (cval + 0) -- simulates a stack
     end ix
   intermediates = 
   loop bi = 0 to 9
     intermediates = intermediates bukits[bi] -- sumulates unstack
     end bi
   -- reload array
   loop iw = 1 to intermediates.words()
     tlist[iw - 1] = intermediates.word(iw)
     end iw
   end px
 -- restore the array to original scale
 tlist = rescale(tlist, -minn)
 return tlist

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method rescale(arry = Rexx[], newbase) private static returns Rexx[]

 loop ix = 0 to arry.length - 1
   arry[ix] = arry[ix] - newbase
   end ix
 return arry

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method getLimits(arry = Rexx[]) private static returns Rexx

 maxn = 0
 minn = 0
 maxl = 0
 loop i_ = 0 to arry.length - 1
   maxn = maxn.max(arry[i_])
   minn = minn.min(arry[i_])
   end i_
 maxl = (maxn - minn).length()
 return maxn minn maxl

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method runSample(arg) private static

 lists = [-
   [2, 24, 45, 0, 66, 75, 170, -802, -90, 1066, 666], -
   [170, 45, 75, 90, 2, 24, 802, 66], -
   [10, 9, 8, 7, 8, 5, 4, 3, 2, 1, 0], -
   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], -
   [-10, -9, -8, -7, -8, -5, -4, -3, -2, -1, -0], -
   [-0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10], -
   [-10, -19, -18, -17, -18, -15, -14, -13, -12, -11, -100], -
   [10, 9, 8, 7, 8, 5, 4, 3, 2, 1, 0, -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10], -
   [-10, -9, -8, -7, -8, -5, -4, -3, -2, -1, -0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -
 ]
 loop il = 0 to lists.length - 1
   tlist = lists[il]
   say ' Input:' Arrays.asList(tlist)
   say 'Output:' Arrays.asList(radixSort(tlist))
   say
   end il
 return

</lang>

Output:
 Input: [2, 24, 45, 0, 66, 75, 170, -802, -90, 1066, 666]
Output: [-802, -90, 0, 2, 24, 45, 66, 75, 170, 666, 1066]

 Input: [170, 45, 75, 90, 2, 24, 802, 66]
Output: [2, 24, 45, 66, 75, 90, 170, 802]

 Input: [10, 9, 8, 7, 8, 5, 4, 3, 2, 1, 0]
Output: [0, 1, 2, 3, 4, 5, 7, 8, 8, 9, 10]

 Input: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

 Input: [-10, -9, -8, -7, -8, -5, -4, -3, -2, -1, 0]
Output: [-10, -9, -8, -8, -7, -5, -4, -3, -2, -1, 0]

 Input: [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]
Output: [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0]

 Input: [-10, -19, -18, -17, -18, -15, -14, -13, -12, -11, -100]
Output: [-100, -19, -18, -18, -17, -15, -14, -13, -12, -11, -10]

 Input: [10, 9, 8, 7, 8, 5, 4, 3, 2, 1, 0, 0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10]
Output: [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 0, 1, 2, 3, 4, 5, 7, 8, 8, 9, 10]

 Input: [-10, -9, -8, -7, -8, -5, -4, -3, -2, -1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Output: [-10, -9, -8, -8, -7, -5, -4, -3, -2, -1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Using Collection classes

<lang NetRexx>/* NetRexx */ options replace format comments java crossref symbols nobinary

import java.util.Queue

runSample(arg) return

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method radixSort(tlist = Rexx[]) public static returns Rexx[]

 -- scale the array to start at zero to allow handling of -ve values
 limits = 
 parse '!MAXN !MINN !MAXL' maxn_ minn_ maxl_ .
 parse getLimits(tlist) maxn minn maxl .
 limits[maxn_] = maxn
 limits[minn_] = minn
 limits[maxl_] = maxl
 tlist = rescale(tlist, limits[minn_])
 loop px = limits[maxl_] to 1 by -1
   bukits = Queue[10] -- stacks for digits 0 .. 9
   loop ix = 0 while ix < tlist.length
     cval = tlist[ix].right(limits[maxl_], 0)
     parse cval . =(px) digit +1 . -- extract next digit (fun with parse)
     -- alternatively: digit = (cval % (10 ** (px - 1))) // 10
     if bukits[digit] == null then bukits[digit] = LinkedList()
     bukits[digit].add((cval + 0))
     end ix
   intermediates = ArrayList()
   loop bi = 0 to 9
     if bukits[bi] \= null then loop while bukits[bi].size() > 0
       nextd = bukits[bi].poll()
       intermediates.add(nextd)
       end
     end bi
   -- reload result array
   loop iw = 0 while iw < intermediates.size()
     tlist[iw] = Rexx intermediates.get(iw)
     end iw
   end px
 -- restore the array to original scale
 tlist = rescale(tlist, -limits[minn_])
 return tlist

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method rescale(arry = Rexx[], newbase) private static returns Rexx[]

 loop ix = 0 to arry.length - 1
   arry[ix] = arry[ix] - newbase
   end ix
 return arry

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method getLimits(arry = Rexx[]) private static returns Rexx

 maxn = 0
 minn = 0
 maxl = 0
 loop i_ = 0 to arry.length - 1
   maxn = maxn.max(arry[i_])
   minn = minn.min(arry[i_])
   end i_
 maxl = (maxn - minn).length()
 return maxn minn maxl

-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ method runSample(arg) private static

 lists = [-
   [2, 24, 45, 0, 66, 75, 170, -802, -90, 1066, 666], -
   [170, 45, 75, 90, 2, 24, 802, 66], -
   [10, 9, 8, 7, 8, 5, 4, 3, 2, 1, 0], -
   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], -
   [-10, -9, -8, -7, -8, -5, -4, -3, -2, -1, -0], -
   [-0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10], -
   [-10, -19, -18, -17, -18, -15, -14, -13, -12, -11, -100], -
   [10, 9, 8, 7, 8, 5, 4, 3, 2, 1, 0, -0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10], -
   [-10, -9, -8, -7, -8, -5, -4, -3, -2, -1, -0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -
 ]
 loop il = 0 to lists.length - 1
   tlist = lists[il]
   say ' Input:' Arrays.asList(tlist)
   say 'Output:' Arrays.asList(radixSort(tlist))
   say
   end il
 return

</lang>

Perl

Radix sort in base 10. <lang perl>#!/usr/bin/perl use warnings; use strict;

sub radix {

   my @tab = ([@_]);
   my $max_length = 0;
   length > $max_length and $max_length = length for @_;
   $_ = sprintf "%0${max_length}d", $_ for @{ $tab[0] }; # Add zeros.
   for my $pos (reverse -$max_length .. -1) {
       my @newtab;
       for my $bucket (@tab) {
           for my $n (@$bucket) {
               my $char = substr $n, $pos, 1;
               $char = -1 if '-' eq $char;
               $char++;
               push @{ $newtab[$char] }, $n;
           }
       }
       @tab = @newtab;
   }
   my @return;
   my $negative = shift @tab;                            # Negative bucket must be reversed.
   push @return, reverse @$negative;
   for my $bucket (@tab) {
       push @return, @{ $bucket // [] };
   }
   $_ = 0 + $_ for @return;                              # Remove zeros.
   return @return;

}</lang> To test, add the following lines: <lang perl>use Test::More tests => 1000;

for (1 .. 1000) {

   my @l = map int rand(2000) - 1000, 0 .. 20;
   is_deeply([radix(@l)], [sort { $a <=> $b } @l]);

}</lang>

Perl 6

A base-10 radix sort, done on the string representation of the integers. Signs are handled by in-place reversal of the '-' bucket on the last iteration. (The sort in there is not cheating; it only makes sure we process the buckets in the right order, since classify might return the buckets in random order. It might be more efficient to create our own ordered buckets, but this is succinct.) <lang perl6>sub radsort (@ints) {

   my $maxlen = [max] @ints».chars;
   my @list = @ints».fmt("\%0{$maxlen}d");
   for reverse ^$maxlen -> $r {
       my @buckets = @list.classify( *.substr($r,1) ).sort: *.key;
       if !$r and @buckets[0].key eq '-' { @buckets[0].value .= reverse }
       @list = map *.value.values, @buckets;
   }
   @list».Int;

}

.say for radsort (-2_000 .. 2_000).roll(20);</lang>

Output:
-1585
-1427
-1228
-1067
-945
-657
-643
-232
-179
-28
37
411
488
509
716
724
1504
1801
1864
1939

PicoLisp

This is a LSD base-2 radix sort using queues: <lang PicoLisp>(de radixSort (Lst)

  (let Mask 1
     (while
        (let (Pos (list NIL NIL)  Neg (list NIL NIL)  Flg)
           (for N Lst
              (queue
                 (if2 (ge0 N) (bit? Mask N)
                    (cdr Pos) Pos Neg (cdr Neg) )
                 N )
              (and (>= (abs N) Mask) (on Flg)) )
           (setq
              Lst (conc (apply conc Neg) (apply conc Pos))
              Mask (* 2 Mask) )
           Flg ) ) )
  Lst )</lang>

Output:

: (radixSort (make (do 12 (link (rand -999 999)))))
-> (-999 -930 -666 -336 -218 68 79 187 391 405 697 922)

PureBasic

<lang PureBasic>Structure bucket

 List i.i()

EndStructure

DataSection

 ;sets specify the size (1 based) followed by each integer
 set1:
 Data.i 10 ;size
 Data.i 1, 3, 8, 9, 0, 0, 8, 7, 1, 6 ;data
 set2:
 Data.i 8 
 Data.i 170, 45, 75, 90, 2, 24, 802, 66
 set3:
 Data.i 8
 Data.i 170, 45, 75, 90, 2, 24, -802, -66

EndDataSection

Procedure setIntegerArray(Array x(1), *setPtr)

 Protected i, count
 count = PeekI(*setPtr) - 1 ;convert to zero based count
 *setPtr + SizeOf(Integer) ;move pointer forward to data
 Dim x(count)
 For i = 0 To count
   x(i) = PeekI(*setPtr + i * SizeOf(Integer))
 Next 

EndProcedure

Procedure displayArray(Array x(1))

 Protected i, Size = ArraySize(x())
 For i = 0 To Size
   Print(Str(x(i)))
   If i < Size: Print(", "): EndIf
 Next 
 PrintN("")

EndProcedure

Procedure radixSort(Array x(1), Base = 10)

 Protected count = ArraySize(x())
 If Base < 1 Or count < 1: ProcedureReturn: EndIf ;exit due to invalid values
 
 Protected i, pv, digit, digitCount, maxAbs, pass, index
 ;find element with largest number of digits
 For i = 0 To count
   If Abs(x(i)) > maxAbs
     maxAbs = Abs(x(i))
   EndIf 
 Next
 
 digitCount = Int(Log(maxAbs)/Log(Base)) + 1
 
 For pass = 1 To digitCount
   Dim sortBuckets.bucket(Base * 2 - 1)
   pv = Pow(Base, pass - 1)
   
   ;place elements in buckets according to the current place-value's digit
   For index = 0 To count
     digit = Int(x(index)/pv) % Base + Base
     AddElement(sortBuckets(digit)\i())
     sortBuckets(digit)\i() = x(index)
   Next
   
   ;transfer contents of buckets back into array
   index = 0
   For digit = 1 To (Base * 2) - 1
     ForEach sortBuckets(digit)\i()
       x(index) = sortBuckets(digit)\i()
       index + 1
     Next 
   Next
 Next

EndProcedure

If OpenConsole()

 Dim x(0)
 setIntegerArray(x(), ?set1)
 radixSort(x()): displayArray(x())
 
 setIntegerArray(x(), ?set2)
 radixSort(x()): displayArray(x())
 
 setIntegerArray(x(), ?set3)
 radixSort(x(), 2): displayArray(x())
 
 Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
 CloseConsole()

EndIf</lang> Sample output:

0, 0, 1, 1, 3, 6, 7, 8, 8, 9
2, 24, 45, 66, 75, 90, 170, 802
-802, -66, 2, 24, 45, 75, 90, 170

Python

Works with: Python version 2.6

This is the Wikipedia example code extended with an extra pass to sort negative values correctly.

<lang python>#python2.6 < from math import log

def getDigit(num, base, digit_num):

   # pulls the selected digit
   return (num // base ** digit_num) % base  

def makeBlanks(size):

   # create a list of empty lists to hold the split by digit
   return [ [] for i in range(size) ]  

def split(a_list, base, digit_num):

   buckets = makeBlanks(base)
   for num in a_list:
       # append the number to the list selected by the digit
       buckets[getDigit(num, base, digit_num)].append(num)  
   return buckets

  1. concatenate the lists back in order for the next step

def merge(a_list):

   new_list = []
   for sublist in a_list:
      new_list.extend(sublist)
   return new_list

def maxAbs(a_list):

   # largest abs value element of a list
   return max(abs(num) for num in a_list)

def split_by_sign(a_list):

   # splits values by sign - negative values go to the first bucket,
   # non-negative ones into the second
   buckets = [[], []]
   for num in a_list:
       if num < 0:
           buckets[0].append(num)
       else:
           buckets[1].append(num)
   return buckets

def radixSort(a_list, base):

   # there are as many passes as there are digits in the longest number
   passes = int(round(log(maxAbs(a_list), base)) + 1) 
   new_list = list(a_list)
   for digit_num in range(passes):
       new_list = merge(split(new_list, base, digit_num))
   return merge(split_by_sign(new_list))

</lang>

Racket

<lang racket>

  1. lang racket

(require data/queue)

(define (radix-sort l r)

 (define queues (for/vector #:length r ([_ r]) (make-queue)))
 (let loop ([l l] [R 1])
   (define all-zero? #t)
   (for ([x (in-list l)])
     (define x/R (quotient x R))
     (enqueue! (vector-ref queues (modulo x/R r)) x)
     (unless (zero? x/R) (set! all-zero? #f)))
   (if all-zero? l
       (loop (let q-loop ([i 0])
               (define q (vector-ref queues i))
               (let dq-loop ()
                 (if (queue-empty? q)
                   (if (< i (sub1 r)) (q-loop (add1 i)) '())
                   (cons (dequeue! q) (dq-loop)))))
             (* R r)))))

(for/and ([i 10000]) ; run some tests on random lists with a random radix

 (define (make-random-list)
   (for/list ([i (+ 10 (random 10))]) (random 100000)))
 (define (sorted? l)
   (match l [(list) #t] [(list x) #t]
          [(list x y more ...) (and (<= x y) (sorted? (cons y more)))]))
 (sorted? (radix-sort (make-random-list) (+ 2 (random 98)))))
=> #t, so all passed

</lang>

REXX

This REXX version works with malformed integers. <lang rexx>/*REXX program performs a radix sort on a stemmed integer array. */ aList='0 2 3 4 5 5 7 6 6 7 11 7 13 9 8 8 17 8 19 9 10 13 23 9 10 15 9 11',

     '29 10 31 10 14 19 12 10 37 21 16 11 41 12 43 15 11 25 47 11 14 12',
     '20 17 53 11 16 13 22 31 59 12 61 33 13 12 18 16 67 21 26 14 71 12',
     '73 39 13 23 18 18 79 13 12 43 83 14 22 45 32 17 89 13 20 27 34 49',
     '24 13 97 16 17 14 101 22 103 19 15 55 107 13 109 18 40 15 113 -42'

/*excluding -42, the abbreviated list is called the integer log function*/ mina=word(aList,1); maxa=mina

    do n=1  for words(aList); x=word(aList,n); @.n=x  /*list ──► array.*/
    mina =min(x,mina);  maxa=max(x,maxa)
    width=max(length(abs(mina)),length(maxa))
    end   /*n*/

n=words(aList); w=length(n); call radSort n

        do j=1  for n
        say 'item' right(j,w) "after the radix sort:"  right(@.j,width+1)
        end    /*j*/

exit /*stick a fork in it, we're done.*/ /*───────────────────────────────────RADSORT subroutine─────────────────*/ radSort: procedure expose @. width; parse arg size; mote=c2d(' '); #=1 !.#._b=1;  !.#._i=1 !.#._n=size; do i=1 for size; y=@.i; @.i=right(abs(y),width,0)

                if y<0  then @.i='-'@.i
                end   /*i*/

/*══════════════════════════════════════where the rubber meets the road.*/

 do while #\==0; ctr.=0; L='ffff'x; low=!.#._b; n=!.#._n; radi=!.#._i; H=
 #=#-1
       do j=low  for n;     parse var @.j =(radi) _ +1;     ctr._=ctr._+1
       if ctr._==1  then if _\==  then do
                                         if _<<L  then L=_
                                         if _>>H  then H=_
                                         end
       end   /*j*/
 if L>>H  then iterate
 _=
 if L==H  then if ctr._==0  then do;  #=#+1;   !.#._b=low
                                               !.#._n=n
                                               !.#._i=radi+1;     iterate
                                 end
 L=c2d(L);  H=c2d(H);    ?=ctr._+low;      top._=?;    ts=mote;     max=L
              do k=L  to H;    _=d2c(k,1);    cen=ctr._
              if cen>ts  then  parse value    cen  k    with    ts  max
              ?=?+cen;   top._=?
              end   /*k*/
 pivot=low
    do  while  pivot<low+n;         it=@.pivot
         do forever
         parse var it =(radi) _ +1; cen=top._-1; if pivot>=cen then leave
         top._=cen;  ?=@.cen;  @.cen=it;  it=?
         end    /*forever*/
    top._=pivot;     @.pivot=it;    pivot=pivot+ctr._
    end         /*while pivot<low+n*/
 i=max
     do until i==max;   _=d2c(i,1);   i=i+1;   if i>H then i=L;   d=ctr._
     if d<=mote then do; if d>1 then call .radSortP top._,d; iterate; end
     #=#+1;     !.#._b=top._
                !.#._n=d
                !.#._i=radi+1
     end   /*until i==max*/
 end       /*while #\==0 */

/*═════════════════════════════════════we're done with the heavy lifting*/

  1. =0; do i=size by -1 to 1; if @.i>=0 then iterate; #=#+1; @@.#=@.i; end
      do j=1 for size;      if @.j <0  then iterate; #=#+1; @@.#=@.j; end
      do k=1 for size;  @.k=@@.k+0; end  /*combine neg&pos radix lists*/

return /*───────────────────────────────────.radSortP subroutine───────────────*/ .radSortP: parse arg bbb,nnn

         do k=bbb+1  for nnn-1;    q=@.k
             do j=k-1 by -1 to bbb while q<<@.j;  jp=j+1;  @.jp=@.j;  end
         jp=j+1;      @.jp=q
         end   /*k*/

return</lang> output (with the middle section elided.)

item   1 after the radix sort:  -42
item   2 after the radix sort:    0
item   3 after the radix sort:    2
item   4 after the radix sort:    3
item   5 after the radix sort:    4
item   6 after the radix sort:    5
item   7 after the radix sort:    5
item   8 after the radix sort:    6
item   9 after the radix sort:    6
item  10 after the radix sort:    7
item  11 after the radix sort:    7
item  12 after the radix sort:    7
item  13 after the radix sort:    8
  .
  .
  .
(middle section elided.)
  .
  .
  .
item  92 after the radix sort:   40
item  93 after the radix sort:   41
item  94 after the radix sort:   43
item  95 after the radix sort:   43
item  96 after the radix sort:   45
item  97 after the radix sort:   47
item  98 after the radix sort:   49
item  99 after the radix sort:   53
item 100 after the radix sort:   55
item 101 after the radix sort:   59
item 102 after the radix sort:   61
item 103 after the radix sort:   67
item 104 after the radix sort:   71
item 105 after the radix sort:   73
item 106 after the radix sort:   79
item 107 after the radix sort:   83
item 108 after the radix sort:   89
item 109 after the radix sort:   97
item 110 after the radix sort:  101
item 111 after the radix sort:  103
item 112 after the radix sort:  107
item 113 after the radix sort:  109
item 114 after the radix sort:  113

Ruby

Negative number handling courtesy the Tcl solution. <lang ruby>class Array

 def radix_sort(base=10)
   ary = dup
   rounds = (Math.log(ary.minmax.map(&:abs).max)/Math.log(base)).floor + 1
   rounds.times do |i|
     buckets = Array.new(2*base){[]}
     base_i = base**i
     ary.each do |n|
       digit = (n/base_i) % base
       digit += base if 0<=n
       buckets[digit] << n
     end
     ary = buckets.flatten
     p [i, ary] if $DEBUG
   end
   ary
 end
 def radix_sort!(base=10)
   replace radix_sort(base)
 end

end

p [1, 3, 8, 9, 0, 0, 8, 7, 1, 6].radix_sort p [170, 45, 75, 90, 2, 24, 802, 66].radix_sort p [170, 45, 75, 90, 2, 24, -802, -66].radix_sort p [100000, -10000, 400, 23, 10000].radix_sort</lang>

running with $DEBUG on produces:

[0, [0, 0, 1, 1, 3, 6, 7, 8, 8, 9]]
[0, 0, 1, 1, 3, 6, 7, 8, 8, 9]
[0, [170, 90, 2, 802, 24, 45, 75, 66]]
[1, [2, 802, 24, 45, 66, 170, 75, 90]]
[2, [2, 24, 45, 66, 75, 90, 170, 802]]
[2, 24, 45, 66, 75, 90, 170, 802]
[0, [-66, -802, 170, 90, 2, 24, 45, 75]]
[1, [-66, -802, 2, 24, 45, 170, 75, 90]]
[2, [-802, -66, 2, 24, 45, 75, 90, 170]]
[-802, -66, 2, 24, 45, 75, 90, 170]
[0, [-10000, 100000, 400, 10000, 23]]
[1, [-10000, 100000, 400, 10000, 23]]
[2, [-10000, 100000, 10000, 23, 400]]
[3, [-10000, 100000, 10000, 23, 400]]
[4, [-10000, 100000, 23, 400, 10000]]
[5, [-10000, 23, 400, 10000, 100000]]
[-10000, 23, 400, 10000, 100000]

another version (After sorting at the absolute value, it makes a negative order reverse.) <lang ruby>class Array

 def radix_sort(base=10)
   ary = dup
   m, max = 1, ary.minmax.map(&:abs).max
   while m <= max
     buckets = Array.new(base){[]}
     ary.each {|n| buckets[(n.abs / m) % base] << n}
     ary = buckets.flatten
     m *= base
   end
   ary.partition{|n| n<0}.inject{|minus,plus| minus.reverse + plus}
 end

end</lang>

Tcl

Translation of: Python

<lang tcl>package require Tcl 8.5 proc splitByRadix {lst base power} {

   # create a list of empty lists to hold the split by digit
   set out [lrepeat [expr {$base*2}] {}]
   foreach item $lst {

# pulls the selected digit set digit [expr {($item / $base ** $power) % $base + $base * ($item >= 0)}] # append the number to the list selected by the digit lset out $digit [list {*}[lindex $out $digit] $item]

   }
   return $out

}

  1. largest abs value element of a list

proc tcl::mathfunc::maxabs {lst} {

   set max [abs [lindex $lst 0]]
   for {set i 1} {$i < [llength $lst]} {incr i} {

set v [abs [lindex $lst $i]] if {$max < $v} {set max $v}

   }
   return $max

}

proc radixSort {lst {base 10}} {

   # there are as many passes as there are digits in the longest number
   set passes [expr {int(log(maxabs($lst))/log($base) + 1)}]
   # For each pass...
   for {set pass 0} {$pass < $passes} {incr pass} {

# Split by radix, then merge back into the list set lst [concat {*}[splitByRadix $lst $base $pass]]

   }
   return $lst

}</lang> Demonstrations: <lang tcl>puts [radixSort {1 3 8 9 0 0 8 7 1 6}] puts [radixSort {170 45 75 90 2 24 802 66}] puts [radixSort {170 45 75 90 2 24 -802 -66}]</lang> Output:

0 0 1 1 3 6 7 8 8 9
2 24 45 66 75 90 170 802
-802 -66 2 24 45 75 90 170

zkl

In place int sort, fairly light on garbage creation. <lang zkl>fcn radixSort(ns){ // ints only, inplace, ns is mutable

  b:=(0).pump(20,List,List.create.fpM("-"));  // 20 buckets: -10..10
  z:=ns.reduce(fcn(a,b){if(a.abs()>b.abs()) a else b},0); // max # digits
  m:=1;
  while(z){
     ns.apply2('wrap(n){b[(n/m)%10 +10].append(n)});    
     ns.clear(); b.apply2(ns.extend); // flatten ie sorted on mth digit
     b.apply("clear");  // reset buckets
     m *= 10; z /= 10;
  }
  ns

}</lang> <lang zkl>radixSort(T(170, 45, 75, 90, 802, 2, 24, 66)).println(); radixSort(T(170, 45, 75, -90, -802, 24, 2, 66)).println();</lang>

Output:
L(2,24,45,66,75,90,170,802)
L(-802,-90,2,24,45,66,75,170)