Sorting algorithms/Selection sort: Difference between revisions

From Rosetta Code
Line 484: Line 484:
 
<lang python>def selectionSort(lst):
 
<lang python>def selectionSort(lst):
 
for i in range(0,len(lst)-1):
 
for i in range(0,len(lst)-1):
mn = i
+
mn = min(range(i,len(lst)), key=lst.__getitem__)
for j in range(i+1,len(lst)):
 
if lst[j] < lst[mn]:
 
mn = j
 
 
lst[i],lst[mn] = lst[mn],lst[i]
 
lst[i],lst[mn] = lst[mn],lst[i]
 
return lst</lang>
 
return lst</lang>
  +
 
 
=={{header|R}}==
 
=={{header|R}}==
 
For loop:
 
For loop:

Revision as of 22:56, 18 October 2009

Task
Sorting algorithms/Selection 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 array (or list) of elements using the Selection sort algorithm. It works as follows:

First find the smallest element in the array and exchange it with the element in the first position, then find the second smallest element and exchange it with the element in the second position, and continue in this way until the entire array is sorted. Its asymptotic complexity is O(n2) making it inefficient on large arrays.

Ada

<lang ada> with Ada.Text_IO; use Ada.Text_IO;

procedure Test_Selection_Sort is

  type Integer_Array is array (Positive range <>) of Integer;
  procedure Sort (A : in out Integer_Array) is
     Min  : Positive;
     Temp : Integer;
  begin
     for I in A'First..A'Last - 1 loop
        Min := I;
        for J in I + 1..A'Last loop
           if A (Min) > A (J) then
              Min := J;
           end if;
        end loop;
        if Min /= I then
           Temp    := A (I);
           A (I)   := A (Min);
           A (Min) := Temp;
        end if;
     end loop;
  end Sort;
  A : Integer_Array := (4, 9, 3, -2, 0, 7, -5, 1, 6, 8);

begin

  Sort (A);
  for I in A'Range loop
     Put (Integer'Image (A (I)) & " ");
  end loop;

end Test_Selection_Sort; </lang> Sample output:

-5 -2  0  1  3  4  6  7  8  9

ALGOL 68

Translation of: Ada
Works with: ALGOL 68 version Standard - no extensions to language used
Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386

<lang algol> MODE DATA = REF CHAR;

PROC in place selection sort = (REF[]DATA a)VOID: BEGIN

  INT min;
  DATA temp;
  FOR i FROM LWB a TO UPB a DO
     min := i;
     FOR j FROM i + 1 TO UPB a DO
        IF a [min] > a [j] THEN
           min := j
        FI
     OD;
     IF min /= i THEN
        temp    := a [i];
        a [i]   := a [min];
        a [min] := temp
     FI
  OD

END # in place selection sort #;

[32]CHAR data := "big fjords vex quick waltz nymph"; [UPB data]DATA ref data; FOR i TO UPB data DO ref data[i] := data[i] OD; in place selection sort(ref data); FOR i TO UPB ref data DO print(ref data[i]) OD; print(new line); print((data)) </lang> Output:

     abcdefghiijklmnopqrstuvwxyz
big fjords vex quick waltz nymph

AutoHotkey

ahk forum: discussion <lang AutoHotkey>MsgBox % SelecSort("") MsgBox % SelecSort("xxx") MsgBox % SelecSort("3,2,1") MsgBox % SelecSort("dog,000000,xx,cat,pile,abcde,1,cat,zz,xx,z")

SelecSort(var) {  ; SORT COMMA SEPARATED LIST

  StringSplit a, var, `,                ; make array, size = a0
  Loop % a0-1 {
     i := A_Index, mn := a%i%, j := m := i
     Loop % a0-i {                      ; find minimum
         j++
         If (a%j% < mn)
            mn := a%j%, m := j
     }
     t := a%i%, a%i% := a%m%, a%m% := t ; swap first with minimum
  }
  Loop % a0                             ; construct string from sorted array
     sorted .= "," . a%A_Index%
  Return SubStr(sorted,2)               ; drop leading comma

}</lang>

AWK

<lang awk>function getminindex(gl, gi, gs) {

 min = gl[gi]
 gm = gi
 for(gj=gi; gj <= gs; gj++) {
   if ( gl[gj] < min ) {
     min = gl[gj]
     gm = gj
   }
 }
 return gm

}

{

 line[NR] = $0

} END { # sort it with selection sort

 for(i=1; i <= NR; i++) {
   mi = getminindex(line, i, NR)
   t = line[i]
   line[i] = line[mi];
   line[mi] = t
 }
 #print it
 for(i=1; i <= NR; i++) {
   print line[i]
 }

}</lang>

C

<lang c>#include <stdio.h>


int getminindex(int *a, int s, int b) {

 int i, min=a[s], mi=s;
 for(i=s; i < b; i++)
 {
   if ( a[i] < min ) { min = a[i]; mi = i; }
 }
 return mi;

}

void selectionsort(int *a, int s) {

 int i, t, mi;
 for(i=0; i<s ; i++)
 {
    mi = getminindex(a, i, s);
    t = a[i]; a[i] = a[mi]; a[mi] = t; 
 }

}


int main() {

  int ar[] = { 5, 200, 1, 65, 30, 99, 2, 0 };
  int i;
  
  selectionsort(ar, 8);
  for(i=0; i<8; i++)
  {
    printf("%d\n", ar[i]);
  }
  
  return 0;

} </lang>

Sample output

0
1
2
5
30
65
99
200

C++

Compiler: g++ (version 4.3.2 20081105 (Red Hat 4.3.2-7))

<lang cpp>#include <algorithm>

  1. include <iterator>

template<typename ForwardIterator> void selectionSort(ForwardIterator begin, ForwardIterator end) {

 ForwardIterator i = begin;
 while(i != end) {
   ForwardIterator j = i;
   ForwardIterator min = i;
   while(j != end) {
     if(*j < *min) {
       min = j;
     }
     ++j;
   }
   std::iter_swap(i, min);
   ++i;
 }

}

</lang>

Common Lisp

<lang lisp>(defun selection-sort-vector (array predicate)

 (do ((length (length array))
      (i 0 (1+ i)))
     ((eql i length) array)
   (do ((mindex i)
        (min (aref array i))
        (j i (1+ j)))
       ((eql j length)
        (rotatef (aref array i) (aref array mindex)))
     (when (funcall predicate (aref array j) min)
       (setf min (aref array j)
             mindex j)))))

(defun selection-sort-list (list predicate)

 (flet ((min-first (list)
          (do ((before-min nil)
               (min (first list))
               (prev list (rest prev))
               (curr (rest list) (rest curr)))
              ((endp curr)
               (if (null before-min) list
                 (let ((min (cdr before-min)))
                   (rplacd before-min (cdr min))
                   (rplacd min list)
                   min)))
            (when (funcall predicate (first curr) min)
              (setf before-min prev
                    min (first curr))))))
   (let ((result (min-first list)))
     (do ((head result (rest head)))
         ((endp (rest head)) result)
       (rplacd head (min-first (rest head)))))))

(defun selection-sort (sequence predicate)

 (etypecase sequence
   (list (selection-sort-list sequence predicate))
   (vector (selection-sort-vector sequence predicate))))</lang>

Example use:

> (selection-sort (list 8 7 4 3 2 0 9 1 5 6) '<)
(0 1 2 3 4 5 6 7 8 9)

> (selection-sort (vector 8 7 4 3 2 0 9 1 5 6) '>)
#(9 8 7 6 5 4 3 2 1 0)

D

<lang d> // Written in D 2.0.

import std.stdio;

void swap(T)(ref T lhs, ref T rhs) {

   T temp = lhs;
   lhs = rhs;
   rhs = temp;

}

void selectionSort(T)(T[] data) {

   foreach(i; 0..data.length) {
       size_t minIndex = i;
       foreach(j; i + 1..data.length) {
           if(data[j] < data[minIndex]) {
               minIndex = j;
           }
       }
       swap(data[i], data[minIndex]);
   }

}

void main() {

   auto foo = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2];
   selectionSort(foo);
   writeln(foo);

} </lang>

E

<lang e>def selectionSort := {

 def cswap(c, a, b) {
   def t := c[a]
   c[a]  := c[b]
   c[b]  := t
   println(c)
 }
 
 def indexOfMin(array, first, last) {
   var min := array[first]
   var mini := first
   for i in (first+1)..last {
     if (array[i] < min) {
       min := array[i]
       mini := i
     }
   }
   return mini
 }
 /** Selection sort (in-place). */
 def selectionSort(array) {
   def last := (array.size()-1)
   for i in 0..(last - 1) {
     cswap(array, i, indexOfMin(array, i + 1, last))
   }
 }

}</lang>

Forth

<lang forth> defer less? ' < is less?

least ( start end -- least )
 over cell+ do
   i @ over @ less? if drop i then
 cell +loop ;
selection ( array len -- )
 cells over + tuck ( end start end )
 cell- swap do   ( end )
   i over least ( end least )
   i @ over @ i ! swap !
 cell +loop drop ;

create array 8 , 1 , 4 , 2 , 10 , 3 , 7 , 9 , 6 , 5 ,

array 10 selection array 10 cells dump </lang>

Fortran

Works with: Fortran version 95 and later

<lang fortran> PROGRAM SELECTION

 IMPLICIT NONE
 INTEGER :: intArray(10) = (/ 4, 9, 3, -2, 0, 7, -5, 1, 6, 8 /)

 WRITE(*,"(A,10I5)") "Unsorted array:", intArray
 CALL Selection_sort(intArray)
 WRITE(*,"(A,10I5)") "Sorted array  :", intArray
  

CONTAINS

 SUBROUTINE Selection_sort(a)
   INTEGER, INTENT(IN OUT) :: a(:)
   INTEGER :: i, minIndex, temp
   DO i = 1, SIZE(a)-1
      minIndex = MINLOC(a(i:), 1) + i - 1
      IF (a(i) > a(minIndex)) THEN
         temp = a(i)
         a(i) = a(minIndex)
         a(minIndex) = temp
      END IF
   END DO
 END SUBROUTINE Selection_sort

END PROGRAM SELECTION </lang> Output:

Unsorted array:    4    9    3   -2    0    7   -5    1    6    8
Sorted array  :   -5   -2    0    1    3    4    6    7    8    9

Haskell

<lang haskell>selectionSort [] = [] selectionSort (first:lst) = selectR first [] lst where

  selectR small output [] = small : selectionSort output
  selectR small output (x:xs) | x < small = selectR x (small:output) xs
                              | otherwise = selectR small (x:output) xs</lang>

J

Create the following script and load it to a J session. <lang j>selectionSort=: verb define data=. y for_xyz. y do.

 temp=. xyz_index }. data
 nvidx=. xyz_index + temp i. <./ temp
 data=. ((xyz_index, nvidx) { data) (nvidx, xyz_index) } data

end. data )</lang>

In an email discussion, Roger_Hui presented the following tacit code: <lang j> ix=: C.~ <@~.@(0, (i. <./))

  ss1=: ({. , $:@}.)@ix^:(*@#)

</lang>

To validate: <lang j> [data=. 6 15 19 12 14 19 0 17 0 14 6 15 19 12 14 19 0 17 0 14

  selectionSort data

0 0 6 12 14 14 15 17 19 19

  ss1 data

0 0 6 12 14 14 15 17 19 19 </lang>

Java

This algorithm sorts in place. The call sort(array) will rearrange the array and not create a new one. <lang java>public static void sort(int[] nums){ for(int currentPlace = 0;currentPlace<nums.length-1;currentPlace++){ int smallest = Integer.MAX_VALUE; int smallestAt = currentPlace+1; for(int check = currentPlace; check<nums.length;check++){ if(nums[check]<smallest){ smallestAt = check; smallest = nums[check]; } } int temp = nums[currentPlace]; nums[currentPlace] = nums[smallestAt]; nums[smallestAt] = temp; } } </lang>

MAXScript

fn selectionSort arr =
(
    local min = undefined
    for i in 1 to arr.count do
    (
        min = i
        for j in i+1 to arr.count do
        (
            if arr[j] < arr[min] then
            (
                min = j
            )
        )
        swap arr[i] arr[min]
    )
    arr
)

data = selectionSort #(4, 9, 3, -2, 0, 7, -5, 1, 6, 8)
print data

OCaml

<lang ocaml>let rec selection_sort = function

   [] -> []
 | first::lst ->
     let rec select_r small output = function
         [] -> small :: selection_sort output
       | x::xs when x < small -> select_r x (small::output) xs
       | x::xs                -> select_r small (x::output) xs
     in
       select_r first [] lst</lang>

Perl

Translation of: Tcl

<lang perl>sub selection_sort

 {my @a = @_;
  foreach my $i (0 .. $#a - 1)
     {my $min = $i + 1;
      $a[$_] < $a[$min] and $min = $_ foreach $min .. $#a;
      $a[$i] > $a[$min] and @a[$i, $min] = @a[$min, $i];}
  return @a;}</lang>

Python

<lang python>def selectionSort(lst):

   for i in range(0,len(lst)-1):
       mn = min(range(i,len(lst)), key=lst.__getitem__)
       lst[i],lst[mn] = lst[mn],lst[i]
   return lst</lang>

R

For loop: <lang r> selectionsort.loop <- function(x) {

  lenx <- length(x)
  for(i in seq_along(x))
  {
     mini <- (i - 1) + which.min(x[i:lenx])
     start_ <- seq_len(i-1)
     x <- c(x[start_], x[mini], x[-c(start_, mini)])
  }
  x

} </lang> Recursive:

(A prettier solution, but, you may need to increase the value of options("expressions") to test it. Also, you may get a stack overflow if the length of the input vector is more than a few thousand.) <lang r> selectionsort.rec <- function(x) {

  if(length(x) > 1)
  {
     mini <- which.min(x)
     c(x[mini], selectionsort(x[-mini]))
  } else x

} </lang>

Ruby

Translation of: Tcl

<lang ruby>class Array

 def selectionsort!
   0.upto(length - 2) do |i|
     (min_idx = i + 1).upto(length - 1) do |j|
       if self[j] < self[min_idx]
         min_idx = j
       end
     end
     if self[i] > self[min_idx]
       self[i], self[min_idx] = self[min_idx], self[i]
     end
   end
   self
 end

end ary = [7,6,5,9,8,4,3,1,2,0] ary.selectionsort!

  1. => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]</lang>

Standard ML

<lang sml>fun selection_sort [] = []

 | selection_sort (first::lst) =
   let
     fun select_r small ([], output) = small :: selection_sort output
       | select_r small (x::xs, output) = 
           if x < small then 
             select_r x (xs, small::output)
           else
             select_r small (xs, x::output)
   in
     select_r first (lst, [])
   end</lang>

Tcl

Uses struct::list package from
Library: tcllib

<lang tcl>package require Tcl 8.5 package require struct::list

proc selectionsort {A} {

   set len [llength $A]
   for {set i 0} {$i < $len - 1} {incr i} {
       set min_idx [expr {$i + 1}]
       for {set j $min_idx} {$j < $len} {incr j} {
           if {[lindex $A $j] < [lindex $A $min_idx]} {
               set min_idx $j
           }
       }
       if {[lindex $A $i] > [lindex $A $min_idx]} {
           struct::list swap A $i $min_idx
       }
   }
   return $A

}

puts [selectionsort {8 6 4 2 1 3 5 7 9}] ;# => 1 2 3 4 5 6 7 8 9</lang>

Ursala

The selection_sort function is parameterized by a relational predicate p. There are no arrays in Ursala so it uses a list, and the selected item is deleted from the list and inserted into another on each iteration rather than swapped with a preceding item of the same list. <lang Ursala>

  1. import std

selection_sort "p" = @iNX ~&l->rx ^(gldif ==,~&r)^/~&l ^|C/"p"$- ~& </lang> This is already a bad way to code a sorting algorithm in this language, but with only a bit more work, we can get a bigger and slower version that more closely simulates the operations of repeatedly reordering an array. <lang Ursala> selection_sort "p" = ~&itB^?a\~&a ^|JahPfatPRC/~& ~=-~BrhPltPClhPrtPCTlrTQrS^D/"p"$- ~& </lang> Here is a test program sorting by the partial order relation on natural numbers. <lang Ursala>

  1. import nat
  2. cast %nL

example = selection_sort(nleq) <294,263,240,473,596,392,621,348,220,815></lang> output:

<220,240,263,294,348,392,473,596,621,815>