I. Introduction

Sorting algorithms are essential tools in computer science for arranging elements in a specific order. In Ruby, there are several sorting algorithms that can be used to sort arrays efficiently. In this article, we will explore some of the most common sorting algorithms in Ruby, including bubble sort, selection sort, insertion sort, quick sort, and merge sort. We will discuss how each algorithm works, provide examples of their implementation in Ruby, and compare their performance characteristics.

Here is list of sorting algorithms we will cover in this article:

  • Bubble sort
  • Selection sort
  • Insertion sort
  • Quick sort
  • Merge sort
  • Heap sort

II. Bubble sort

Bubble sort is a simple sorting algorithm that repeatedly steps through the list to be sorted, compares each pair of adjacent items, and swaps them if they are in the wrong order. The pass through the list is repeated until no swaps are needed, which indicates that the list is sorted.

1. Implementation in Ruby

def bubble_sort(arr)
  n = arr.length
  loop do
    swapped = false

    (n - 1).times do |i|
      if arr[i] > arr[i + 1]
        arr[i], arr[i + 1] = arr[i + 1], arr[i]
        swapped = true
      end
    end

    break unless swapped
  end

  arr
end

# Example usage

arr = [64, 34, 25, 12, 22, 11, 90]
puts "Unsorted array: #{arr}"
puts "Sorted array: #{bubble_sort(arr)}"

Output:

Unsorted array: [64, 34, 25, 12, 22, 11, 90]
Sorted array: [11, 12, 22, 25, 34, 64, 90]

2. Performance

  • Time Complexity: O(n^2) in the worst and average case, O(n) in the best case (when the list is already sorted).
  • Space Complexity: O(1) as it requires only a constant amount of additional space.

3. Use Cases

Bubble sort is suitable for small datasets or when simplicity is more important than performance. It is not recommended for large datasets due to its quadratic time complexity.

III. Selection sort

Selection sort is an in-place comparison sorting algorithm that divides the input list into two parts: the sublist of items already sorted and the sublist of items remaining to be sorted. It repeatedly selects the smallest element from the unsorted sublist and swaps it with the leftmost unsorted element.

1. Implementation in Ruby

def selection_sort(arr)
  n = arr.length

  (n - 1).times do |i|
    min_index = i

    (i + 1...n).each do |j|
      min_index = j if arr[j] < arr[min_index]
    end

    arr[i], arr[min_index] = arr[min_index], arr[i] if min_index != i
  end

  arr
end

# Example usage

arr = [64, 34, 25, 12, 22, 11, 90]
puts "Unsorted array: #{arr}"
puts "Sorted array: #{selection_sort(arr)}"

Output:

Unsorted array: [64, 34, 25, 12, 22, 11, 90]
Sorted array: [11, 12, 22, 25, 34, 64, 90]

2. Performance

  • Time Complexity: O(n^2) in all cases (worst, average, and best).
  • Space Complexity: O(1) as it requires only a constant amount of additional space.

3. Use Cases

Selection sort is suitable for small datasets or when the number of swaps is a concern. It is not recommended for large datasets due to its quadratic time complexity.

IV. Insertion sort

Insertion sort is a simple sorting algorithm that builds the final sorted array one item at a time. It takes each element from the input list and inserts it into its correct position in the sorted array.

1. Implementation in Ruby

def insertion_sort(arr)
  n = arr.length

  (1...n).each do |i|
    key = arr[i]
    j = i - 1

    while j >= 0 && arr[j] > key
      arr[j + 1] = arr[j]
      j -= 1
    end

    arr[j + 1] = key
  end

  arr
end

# Example usage

arr = [64, 34, 25, 12, 22, 11, 90]
puts "Unsorted array: #{arr}"
puts "Sorted array: #{insertion_sort(arr)}"

Output:

Unsorted array: [64, 34, 25, 12, 22, 11, 90]
Sorted array: [11, 12, 22, 25, 34, 64, 90]

2. Performance

  • Time Complexity: O(n^2) in the worst and average case, O(n) in the best case (when the list is already sorted).
  • Space Complexity: O(1) as it requires only a constant amount of additional space.

3. Use Cases

Insertion sort is suitable for small datasets or when the input list is almost sorted. It is not recommended for large datasets due to its quadratic time complexity.

V. Quick sort

Quick sort is a divide-and-conquer sorting algorithm that divides the input list into two sublists based on a pivot element. It then recursively sorts the sublists and combines them to produce the final sorted array.

1. Implementation in Ruby

def quick_sort(arr)
  return arr if arr.length <= 1

  pivot = arr.delete_at(rand(arr.length))
  left, right = arr.partition { |el| el < pivot }

  quick_sort(left) + [pivot] + quick_sort(right)
end

# Example usage

arr = [64, 34, 25, 12, 22, 11, 90]
puts "Unsorted array: #{arr}"
puts "Sorted array: #{quick_sort(arr)}"

Output:

Unsorted array: [64, 34, 25, 12, 22, 11, 90]
Sorted array: [11, 12, 22, 25, 34, 64, 90]

2. Performance

  • Time Complexity: O(n log n) in the average and best case, O(n^2) in the worst case.
  • Space Complexity: O(log n) due to the recursive calls.

3. Use Cases

Quick sort is suitable for large datasets and is often used as the default sorting algorithm in many programming languages due to its average-case time complexity of O(n log n).

VI. Merge sort

Merge sort is a divide-and-conquer sorting algorithm that divides the input list into two sublists, recursively sorts the sublists, and then merges them to produce the final sorted array.

1. Implementation in Ruby

def merge_sort(arr)
  return arr if arr.length <= 1

  mid = arr.length / 2
  left = merge_sort(arr[0...mid])
  right = merge_sort(arr[mid..])

  merge(left, right)
end

def merge(left, right)
  result = []

  until left.empty? || right.empty?
    result << (left.first <= right.first ? left.shift : right.shift)
  end

  result + left + right
end

# Example usage

arr = [64, 34, 25, 12, 22, 11, 90]
puts "Unsorted array: #{arr}"
puts "Sorted array: #{merge_sort(arr)}"

Output:

Unsorted array: [64, 34, 25, 12, 22, 11, 90]
Sorted array: [11, 12, 22, 25, 34, 64, 90]

2. Performance

  • Time Complexity: O(n log n) in all cases (worst, average, and best).
  • Space Complexity: O(n) due to the additional space required for the merge step.

3. Use Cases

Merge sort is suitable for large datasets and is often used when stability is a concern. It has a consistent time complexity of O(n log n) in all cases.

VII. Heap sort

Heap sort is an in-place comparison sorting algorithm that builds a max heap from the input list and repeatedly extracts the maximum element from the heap to produce the final sorted array.

1. Implementation in Ruby

def heap_sort(arr)
  n = arr.length

  (n / 2 - 1).downto(0) { |i| heapify(arr, n, i) }

  (n - 1).downto(1) do |i|
    arr[0], arr[i] = arr[i], arr[0]
    heapify(arr, i, 0)
  end

  arr
end

def heapify(arr, n, i)
  largest = i
  left = 2 * i + 1
  right = 2 * i + 2

  largest = left if left < n && arr[left] > arr[largest]
  largest = right if right < n && arr[right] > arr[largest]

  if largest != i
    arr[i], arr[largest] = arr[largest], arr[i]
    heapify(arr, n, largest)
  end
end

# Example usage

arr = [64, 34, 25, 12, 22, 11, 90]
puts "Unsorted array: #{arr}"
puts "Sorted array: #{heap_sort(arr)}"

Output:

Unsorted array: [64, 34, 25, 12, 22, 11, 90]
Sorted array: [11, 12, 22, 25, 34, 64, 90]

2. Performance

  • Time Complexity: O(n log n) in all cases (worst, average, and best).
  • Space Complexity: O(1) as it requires only a constant amount of additional space.

3. Use Cases

Heap sort is suitable for large datasets and is often used when an in-place sorting algorithm is required. It has a consistent time complexity of O(n log n) in all cases.

VIII. Conclusion

In this article, we explored several common sorting algorithms in Ruby, including bubble sort, selection sort, insertion sort, quick sort, merge sort, and heap sort. Each algorithm has its own characteristics, performance characteristics, and use cases. When choosing a sorting algorithm, it is important to consider the size of the dataset, the desired performance, and the stability of the algorithm. By understanding the strengths and weaknesses of each algorithm, you can select the most appropriate sorting algorithm for your specific use case.