Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's wrong with my selection sort algorithm?

The answer might be obvious to the trained eye, but I've been hitting the books for a few hours now, my eyes are straining, and I can't seem to see the bug.

Below are two implementations of selection sort I wrote, and neither is sorting the input correctly. You can play with this code on an online interpreter.

def selection_sort_enum(array)
  n = array.length - 1

  0.upto(n - 1) do |i|
    smallest = i

    (i + 1).upto(n) do |j|
      smallest = j if array[j] < array[i]
    end

    array[i], array[smallest] = array[smallest], array[i] if i != smallest
  end
end

def selection_sort_loop(array)
  n = array.length - 1
  i = 0
  while i <= n - 1
    smallest = i
    j = i + 1
    while j <= n
      smallest = j if array[j] < array[i]
      j += 1
    end
    array[i], array[smallest] = array[smallest], array[i] if i != smallest
    i += 1
  end
end

Here's the test of the first implementation, selection_sort_enum:

puts "Using enum:"
a1 = [*1..10].shuffle
puts "Before sort: #{a1.inspect}"
selection_sort_enum(a1)
puts "After sort: #{a1.inspect}"

Here's the test of the second implementation, selection_sort_loop:

puts "Using while:"
a2 = [*1..10].shuffle
puts "Before sort: #{a2.inspect}"
selection_sort_enum(a2)
puts "After sort: #{a2.inspect}"

Here's the output of the first implementation, selection_sort_enum:

Using enum:
Before sort: [7, 5, 2, 10, 6, 1, 3, 4, 8, 9]
After sort:  [4, 3, 1, 9, 5, 2, 6, 7, 8, 10]

Here's the output of the second implementation, selection_sort_loop:

Using while:
Before sort: [1, 10, 5, 3, 7, 4, 8, 9, 6, 2]
After sort:  [1, 2, 4, 3, 6, 5, 7, 8, 9, 10]
like image 575
Mohamad Avatar asked Jul 26 '26 21:07

Mohamad


2 Answers

In both the code snippets you are comparing with index i instead of index smallest.

This should work :

def selection_sort_enum(array)
  n = array.length - 1

  0.upto(n - 1) do |i|
    smallest = i

    (i + 1).upto(n) do |j|
      smallest = j if array[j] < array[smallest]
    end
    array[i], array[smallest] = array[smallest], array[i] if i != smallest
  end
end

def selection_sort_loop(array)
  n = array.length - 1
  i = 0
  while i <= n - 1
    smallest = i
    j = i + 1
    while j <= n
      smallest = j if array[j] < array[smallest]
      j += 1
    end
    array[i], array[smallest] = array[smallest], array[i] if i != smallest
    i += 1
  end
end

Output :

Using enum:
Before sort: [5, 6, 7, 9, 2, 4, 8, 1, 10, 3]
After sort: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Using while:
Before sort: [6, 5, 9, 2, 1, 3, 10, 4, 7, 8]
After sort: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Link to solution : http://ideone.com/pKLriY

like image 135
uSeemSurprised Avatar answered Jul 28 '26 15:07

uSeemSurprised


def selection_sort_enum(array)
  n = array.length - 1 

  0.upto(n) do |i| # n instead of (n - 1)
    smallest_index = i

    (i + 1).upto(n) do |j|
      smallest_index = j if array[j] < array[i]
    end

    puts "#{array}", smallest_index
    array[i], array[smallest_index] = array[smallest_index], array[i] if i != smallest_index
  end
end
like image 26
Ilya Avatar answered Jul 28 '26 14:07

Ilya