Counting sort (Scala)

From LiteratePrograms

Jump to: navigation, search
Other implementations: C | C# | Haskell | Java | Python, functional | Scala

Here is a simple Counting sort in Scala:

<<counting_sort>>=
  // scaladoc (javadoc like) documentation 
  /**
  * 
  * @param array : array to sort
  * @param end   : number of elements to sort
  * @param max   : upper bound for array values
  * @param min   : lower bound for array values
  */
  def cSort( array: Array[Int], end: Int, max: Int, min: Int): Unit = {
    // precondition
    assume( end <= array.length 
            && array.subArray(0, end).forall( x => (min <= x && x <= max))) ;
    if ( end < 2) {}  // nothing to sort
    else if (end == 2) {
      if (array( 0) > array(1)) {
        // swap values
        val temp = array(0) ;
        array(0) = array(1) ;
        array(1) = temp ;
      }
    }
    else  {
      val sortRange = max - min +1 
      val count = new Array[Int]( sortRange)  
      val scratch = new Array[Int]( end) 
      def normalized( i: Int) = array( i) - min 
      count_values_and_accumulate
      // now count(normValue) == topmost (if repeated values) of order( normValue)  
      // reposition array values in scratch
      // each value at count( normValue) position 
      // decrementing count( normValue) for next position of repeated values
      for (val i <- Iterator.range( 0, end)) {
        val normValue = normalized( i) ;
        scratch( count( normValue) -1) = array(i) ;
        count( normValue) = count( normValue) -1 ;
      }
      // copy scratch ordered values back into array
      for (val i <- Iterator.range( 0, end)) { 
        array(i) = scratch( i)
      }
    }
  }

Count normalized values and accumulate counters, so each accumulated counter will hold the topmost ordered position for the value it indexes.

<<count_values_and_accumulate>>=
// init counters 
for (val i <- Iterator.range( 0, sortRange)){
  count( i) = 0 ;
}
// count normalized array values
for (val i <- Iterator.range( 0, end)) {
  val normValue = normalized( i) ;
  count( normValue) = count( normValue) +1 ;
}
// accumulate counters
for (val i <- Iterator.range( 1, sortRange)) {
  count( i) = count( i) + count( i -1)
}
/** 
* count(normValue) will hold the number of elements 
* with normalized value less than or equal to normValue, 
* so the topmost (for repeated values) order position
*
* {count(normValue) == 'count elements x where (normalized( x) <= normValue')} 
*/ 


Test module

<<CountingSortTest.scala>>=
package test;
import scala.testing.UnitTest ;
object CountingSortTest extends Application {
  counting_sort
  def test = {
    val sample1 = Array( 5, 3, 7, 10, 2, 7, 3)
    val expected1 = Array( 2, 3, 3, 5, 7, 7, 10)
    val min = List.fromArray( sample1) reduceLeft { (x: Int, y: Int) => Math.min( x,y)} ;
    val max = List.fromArray( sample1) reduceLeft { (x: Int, y: Int) => Math.max( x,y)} ;
    val actual1 = { 
                    cSort( sample1, sample1.length, max, min) ;
                    sample1 
                   }
    UnitTest.assertSameElements(  actual1, expected1)
  }
  test
}

Testing

scala test.CountingSortTest
passed ok
Download code
Views