Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>As <a href="https://stackoverflow.com/questions/1672074/selection-sort-in-functional-scala/1672190#1672190">starblue already said</a>, you need a function that calculates the minimum of a list and returns the list with that element removed. Here is my tail recursive implementation of something similar (as I believe <code>foldl</code> is tail recursive in the standard library), and I tried to make it as functional as possible :). It returns a list that contains all the elements of the original list (but kindof reversed - see the explanation below) with the minimum as a head.</p> <pre><code>def minimum(xs: List[Int]): List[Int] = (List(xs.head) /: xs.tail) { (ys, x) =&gt; if(x &lt; ys.head) (x :: ys) else (ys.head :: x :: ys.tail) } </code></pre> <p>This basically does a fold, starting with a list containing of the first element of <code>xs</code> If the first element of <code>xs</code> is smaller than the head of that list, we pre-append it to the list <code>ys</code>. Otherwise, we add it to the list <code>ys</code> as the second element. And so on recursively, we've folded our list into a new list containing the minimum element as a head and a list containing all the elements of <code>xs</code> (not necessarily in the same order) with the minimum removed, as a tail. Note that this function does not remove duplicates.</p> <p>After creating this helper function, it's now easy to implement selection sort.</p> <pre><code>def selectionSort(xs: List[Int]): List[Int] = if(xs.isEmpty) List() else { val ys = minimum(xs) if(ys.tail.isEmpty) ys else ys.head :: selectionSort(ys.tail) } </code></pre> <p>Unfortunately this implementation is <em>not</em> tail recursive, so it will blow up the stack for large lists. Anyway, you shouldn't use a O(n^2) sort for large lists, but still... it would be nice if the implementation was tail recursive. I'll try to think of something... I think it will look like the implementation of a fold.</p> <p><strong>Tail Recursive!</strong></p> <p>To make it tail recursive, I use quite a common pattern in functional programming - an accumulator. It works a bit backward, as now I need a function called <code>maximum</code>, which basically does the same as <code>minimum</code>, but with the maximum element - its implementation is exact as minimum, but using <code>&gt;</code> instead of <code>&lt;</code>.</p> <pre><code>def selectionSort(xs: List[Int]) = { def selectionSortHelper(xs: List[Int], accumulator: List[Int]): List[Int] = if(xs.isEmpty) accumulator else { val ys = maximum(xs) selectionSortHelper(ys.tail, ys.head :: accumulator) } selectionSortHelper(xs, Nil) } </code></pre> <p><strong>EDIT</strong>: Changed the answer to have the helper function as a subfunction of the selection sort function.</p> <p>It basically accumulates the maxima to a list, which it eventually returns as the base case. You can also see that it is tail recursive by replacing <code>accumulator</code> by <code>throw new NullPointerException</code> - and then inspect the stack trace.</p> <p>Here's a step by step sorting using an accumulator. The left hand side shows the list <code>xs</code> while the right hand side shows the <code>accumulator</code>. The maximum is indicated at each step by a star.</p> <pre><code>64* 25 12 22 11 ------- Nil 11 22 12 25* ------- 64 22* 12 11 ------- 25 64 11 12* ------- 22 25 64 11* ------- 12 22 25 64 Nil ------- 11 12 22 25 64 </code></pre> <p>The following shows a step by step folding to calculate the maximum:</p> <pre><code>maximum(25 12 64 22 11) 25 :: Nil /: 12 64 22 11 -- 25 &gt; 12, so it stays as head 25 :: 12 /: 64 22 11 -- same as above 64 :: 25 12 /: 22 11 -- 25 &lt; 64, so the new head is 64 64 :: 22 25 12 /: 11 -- and stays so 64 :: 11 22 25 12 /: Nil -- until the end 64 11 22 25 12 </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload