I am trying to implement Quick sort in ruby but stuck in how to call recursively after the first partition of pivot. Please help me to understand on how to proceed and also
here is another way to implement quicksort -- as a newbie I think it's easier to understand -- hope it helps someone :) in this implementation the pivot is always the last element in the array -- I'm following the Khan Academy course and that's where I got the inspiration from
def quick_sort(array, beg_index, end_index)
if beg_index < end_index
pivot_index = partition(array, beg_index, end_index)
quick_sort(array, beg_index, pivot_index -1)
quick_sort(array, pivot_index + 1, end_index)
end
array
end
#returns an index of where the pivot ends up
def partition(array, beg_index, end_index)
#current_index starts the subarray with larger numbers than the pivot
current_index = beg_index
i = beg_index
while i < end_index do
if array[i] <= array[end_index]
swap(array, i, current_index)
current_index += 1
end
i += 1
end
#after this swap all of the elements before the pivot will be smaller and
#after the pivot larger
swap(array, end_index, current_index)
current_index
end
def swap(array, first_element, second_element)
temp = array[first_element]
array[first_element] = array[second_element]
array[second_element] = temp
end
puts quick_sort([2,3,1,5],0,3).inspect #will return [1, 2, 3, 5]
Here is a (very) naive quicksort implementation, based on Wikipedia's simple-quicksort pseudocode:
def quicksort(array) #takes an array of integers as an argument
You need a base case, otherwise your recursive calls never terminate
if array.length <= 1
return array
Now pick a pivot:
else
pivot = array.sample
array.delete_at(array.index(pivot)) # remove the pivot
#puts "Picked pivot of: #{pivot}"
less = []
greater = []
Loop through the array, comparing items to pivot and collecting them into less
and greater
arrays.
array.each do |x|
if x <= pivot
less << x
else
greater << x
end
end
Now, recursively call quicksort()
on your less
and greater
arrays.
sorted_array = []
sorted_array << self.quicksort(less)
sorted_array << pivot
sorted_array << self.quicksort(greater)
Return the sorted_array
and you're done.
# using Array.flatten to remove subarrays
sorted_array.flatten!
You can test it with
qs = QuickSort.new
puts qs.quicksort([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5] # true
puts qs.quicksort([5]) == [5] # true
puts qs.quicksort([5, -5, 11, 0, 3]) == [-5, 0, 3, 5, 11] # true
puts qs.quicksort([5, -5, 11, 0, 3]) == [5, -5, 11, 0, 3] # false
This is how I would implement quick sort in Ruby:
def quicksort(*ary)
return [] if ary.empty?
pivot = ary.delete_at(rand(ary.size))
left, right = ary.partition(&pivot.:>)
return *quicksort(*left), pivot, *quicksort(*right)
end
Actually, I would probably make it an instance method of Array
instead:
class Array
def quicksort
return [] if empty?
pivot = delete_at(rand(size))
left, right = partition(&pivot.:>)
return *left.quicksort, pivot, *right.quicksort
end
end
Here is my version of Quicksorting
class QuickSort
def partition(arr, low ,high)
pivot = arr[high]
i = low
for j in low...high
if arr[j] < pivot
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
i = i+1
end
end
temp = arr[i]
arr[i] = arr[high]
arr[high] = temp
return i
end
def sort(arr, low, high)
if (low < high)
pi = partition(arr, low, high)
sort(arr, low, pi-1)
sort(arr, pi+1, high)
end
arr
end
end
arr = [10, 5, 80, 30, 100, 140, 90, 40, 50, 70, 72, 150, 63]
n = arr.length
qs = QuickSort.new
arr = qs.sort(arr, 0, n-1)
puts "Quick Sorted Array ==>#{arr}"
#Quick Sorted Array ==>[5, 10, 30, 40, 50, 63, 70, 72, 80, 90, 100, 140, 150]