"Build a Simple Ruby on Rails Application" was retired on September 16, 2016.
Well done!
You have completed Introduction to Data Structures!
You have completed Introduction to Data Structures!
Instruction
Merge Sort Implementations
Python
# Let's define a recursive merge sort function. As usual, it takes the
# list or sub-list that we want it to sort.
def merge_sort(values):
# Our base case is the same as with Quicksort. If the list has zero or one
# values, there's nothing to sort, so we return it as-is.
if len(values) <= 1:
return values
# If we didn't return, it means we're in the recursive case. So first we need
# to split the list in half. We need to know the index we should split on,
# so we get the length of the list and divide it by 2. So for example if
# there are 8 items in the list, we'll want an index of 4. But what if there
# were an odd number of items in the list, like 7? We can't have an index of
# 3.5, so we'll need to round down in that case. Since we're working in
# Python currently, we can take advantage of a special Python operator that
# divides and rounds the result down: the floor division operator. It
# consists of a double slash.
middle_index = len(values) // 2
# Now we'll use the Python slice syntax to get the left half of the list.
# We'll pass that list to a recursive call to the merge_sort function.
left_values = merge_sort(values[:middle_index])
# We'll also use slice syntax to get the right half of the list, and pass
# that to merge_sort as well.
right_values = merge_sort(values[middle_index:])
# Now we need to merge the two halves together, and sort them as we do it.
# We'll create a list to hold the sorted values.
sorted_values = []
# Now we get to the complicated part - merging the two halves together and
# sorting them as we do it.
# We'll be moving from left to right through the left half of the list,
# copying values over to the sorted_values list as we go. This left_index
# variable will help us keep track of our position.
left_index = 0
# At the same time, we'll also be moving from left to right through the right
# half of the list and copying values over, so we need a separate
# right_index variable to track that position as well.
right_index = 0
# We'll keep looping until we've processed all of the values in both halves
# of the list.
while left_index < len(left_values) and right_index < len(right_values):
# We're looking to copy over the lowest values first. So first we test
# whether the current value on the left side is less than the value on the
# right side.
if left_values[left_index] < right_values[right_index]:
# If the left side value is less, that's what we'll copy to the sorted
# list.
sorted_values.append(left_values[left_index])
# And then we'll move to the next value in the left half of the list.
left_index += 1
# Otherwise, the current value from the right half must have been lower.
else:
# So we'll copy that value to the sorted list instead.
sorted_values.append(right_values[right_index])
# And then we'll move to the next value in the right half of the list.
right_index += 1
# At this point one of the two unsorted halves still has a value remaining,
# and the other is empty. We won't waste time checking which is which.
# We'll just copy the remainder of both lists over to the sorted list.
# The one with a value left will add that value, and the empty one will add
# nothing.
sorted_values += left_values[left_index:]
sorted_values += right_values[right_index:]
# All the numbers from both halves should now be copied to the sorted list,
# so we can return it.
return sorted_values
Swift
Download as an Xcode Playground
import Foundation
/*
We're going to define `mergesort` as a global function that accepts an array. We could define this on an extension of a higher type like `RandomAccessCollection` but that makes the algorithm harder to understand.
Array's `Element` type is defined as a generic type parameter `T` that conforms to `Comparable`
*/
func mergesort<T: Comparable>(_ array: [T]) -> [T] {
// If the list has zero or one values, there's nothing to sort, so we return it as-is
if array.count <= 1 { return array }
// At this point the algorithm is in the recursive portion
// Determine midpoint of array
let mid = array.count/2
// Create left slice of the array and pass through the mergesort function
let left = mergesort(Array(array[0..<mid]))
// Create right half slice and pass through the mergesort function
let right = mergesort(Array(array[mid..<array.count]))
// Merge the two halves together, and sort them in the process
// Create a new array to hold the sorted values
var sorted = Array<T>()
// To eliminate memory reallocation as `sorted` grows, reserve capacity at the
// outset to a number of elements equaling the sum of elements in left and right
sorted.reserveCapacity(left.count + right.count)
// Move from left to right through the left half of the array,
// copying values over to `sorted` in the process. This leftIndex
// variable keeps track of the position in the array
var leftIndex = 0
// Move from left to right through the right half of the array and
// copy values over. Use a separate
// rightIndex variable to track that position as well
var rightIndex = 0
// Keep looping until all of the values in both subarrays
// are processed.
while leftIndex < left.count && rightIndex < right.count {
// Copy the lesser value in to sorted.
// Test whether the current value on the left side is less than the value on the
// right side.
if left[leftIndex] < right[rightIndex] {
// If the left side value is less, copy to `sorted`
sorted.append(left[leftIndex])
// Increment leftIndex to move to next value in left slice
leftIndex += 1
} else {
// Otherwise, copy the current value in right slice to `sorted`
sorted.append(right[rightIndex])
// Increment `rightIndex` to move to next value in right slice
rightIndex += 1
}
}
// At this point one of the two unsorted halves still has a value remaining,
// and the other is empty. We won't waste time checking which is which.
// We'll just copy the remainder of both lists over to the sorted list.
// The one with a value left will add that value, and the empty one will add
// nothing.
sorted.append(contentsOf: left[leftIndex..<left.count])
sorted.append(contentsOf: right[rightIndex..<right.count])
return sorted
}