Sorting algorithms/Radix sort: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 134: Line 134:
{{eff note|J|/:~}}
{{eff note|J|/:~}}


<code>keys f/. data </code> 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 <code>}.</code>.

<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>
<lang j>radixsort=: (] #~ [: +/ =/) i.@(>./)</lang>



Revision as of 05:06, 21 January 2011

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

D

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

auto rdxsort(int 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 = array(r) ; // input is Range => return a new array
   E absMax = reduce!max(map!abs(r)) ;
   immutable passes = 1 + to!int(log(absMax)/log(N)) ;
   foreach(pass;0..passes) {
       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 = reduce!"a~b"(bucket) ;
   }
   return res ;

}

void main() {

   auto a = [170, 45, 75, -90, 2, 24, -802, 66] ;
   writeln(rdxsort(a)) ;
   writeln(rdxsort(map!"1-a"(a))) ;

}</lang> Output :

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

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>

Python

This example is incorrect. Please fix the code and remove this message.

Details: Doesn't handle negative integers.

The wikipedia article cited in the introduction includes a python implementation of LSB radix sort.

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