Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QuickSort Traditional vs Functional Style What Causes This Difference?

Tags:

scala

I am comparing two codes written in scala language.

package chapter01

object QuickSortScalaTime {
  def sortFunctional(xs: Array[Int]): Array[Int] = {
    if (xs.length <= 1) xs
    else {
      val pivot = xs(xs.length / 2)
      Array.concat(sortFunctional(xs filter (pivot >)), xs filter (pivot ==), sortFunctional(xs filter (pivot <)))
    }
  }

  def sortTraditionl(xs: Array[Int]) {
    def swap(i: Int, j: Int) {
      val t = xs(i);
      xs(i) = xs(j);
      xs(j) = t;
    }

    def sort1(l: Int, r: Int) {
      val pivot = xs((l + r) / 2)
      var i = l;
      var j = r;
      while (i <= j) {
        while (xs(i) < pivot) i += 1
        while (xs(j) > pivot) j -= 1
        if (i <= j) {
          swap(i, j)
          i += 1
          j -= 1
        }
      }
      if (l < j) sort1(l, j)
      if (j < r) sort1(i, r)
    }
    sort1(0, xs.length - 1)
  }
  def main(args: Array[String]): Unit = {

    val arr = Array.fill(100000) { scala.util.Random.nextInt(100000 - 1) }
    var t1 = System.currentTimeMillis
    sortFunctional(arr)
    var t2 = System.currentTimeMillis
    println("Functional style : " + (t2-t1))

    t1 = System.currentTimeMillis
    sortTraditionl(arr)
    t2 = System.currentTimeMillis
    println("Traditional style : " + (t2-t1))
  }

}

The first block is written in functional style and the second block is traditional quick sort. The examples are from Odersky's book by the way.

There is a huge difference between traditional and functional.

Functional style : 450
Traditional style : 30

I just wonder what causes this difference. I do not know scala in depth but my initial guess is the traditional one uses no mutation and any closures. And what can we do to improve the performance of functional style ?

like image 852
cgon Avatar asked Jan 02 '14 10:01

cgon


People also ask

Why quicksort is the best sorting technique?

Quick sort is an in-place sorting algorithm. In-place sorting means no additional storage space is needed to perform sorting. Merge sort requires a temporary array to merge the sorted arrays and hence it is not in-place giving Quick sort the advantage of space.

Why quick sort is unstable?

QuickSort is an unstable algorithm because we do swapping of elements according to pivot's position (without considering their original positions).

What is the complexity of quick sort in best and worst cases?

The best-case time complexity of quicksort is O(n*logn). Average Case Complexity - It occurs when the array elements are in jumbled order that is not properly ascending and not properly descending. The average case time complexity of quicksort is O(n*logn).


1 Answers

Well, your functional sort is a bit wrong. It works, but it calls xs.filter three times! So in every call you traverse the list three times, instead of one.

Consider this implementation:

def sort(ls: List[Int]): List[Int] = {
  ls match {
    case Nil => Nil
    case pivot :: tail => {
      val (less, greater) = tail.partition(_ < pivot)
      sort(less) ::: pivot :: sort(greater)
    }
  }
}

I'm not sure it would give you the desired performance, but it avoids unnecessary traversals of the list.

More, you may read the answer described here for an implementation that uses the foldLeft

like image 147
serejja Avatar answered Sep 25 '22 01:09

serejja