- Implement a merge sort algorithm
- Analyze the Big O of merge sort
- Implement a quicksort algorithm
- Analyze the Big O of quicksort
These sorting methods are fairly straight forward, but are O(n²)
This is fine for smaller arrays, but for larger arrays, we can (and must) do better.
Invented by John von Neumann in 1945.
He was a Hungarian-American pure and applied mathematician, physicist, inventor, computer scientist, and polymath.
von Neumann did A LOT in his career, including inventing the Von Neumann Architecture in 1945 which to this day is the basis of modern computer design.
This architecture allows data and a program to co-exist in memory. Before this, computers were programmed by setting switches and inserting patch leads to route data and to control signals between various functional units.
Von Neumann's First Computer Program by Donald E. Knuth
Merge sort works by decomposing the array into smaller chunks, which are then sorted and merged together.
This process goes all the way down to arrays of size 1, which are super easy to sort!
- If your array has a length less than 2, congratulations! It's already sorted.
- Otherwise, cut your array in half, and consider the two sub-arrays separately.
- Sort each of your smaller subarrays using merge sort.
- Merge your two subarrays together, and return the merged array.
In order to implement merge sort, it's useful to have a helper function that takes two sorted arrays and merges them together to create a new, larger sorted array.
function merge(arr1, arr2) {
// 1. declare a new empty array, and pointers corresponding to indices in arr1 and arr2 (set them both to 0)
// 2. if the first element in arr1 is less than the first element in arr2,
// push the first element in arr1 to the new array, and move the pointer for arr1 one spot to the right.
// Otherwise, do this for arr2.
// 3. Repeat this process until you've gone through one of the arrays
// return the new array, concatenated with whatever elements are remaining from the array that you haven't exhausted yet.
}
<iframe class="stretch" src="http://visualgo.net/sorting"></iframe>
n iterations to split the array.
log(n) iterations to merge them back together
O(n) * O(log n) = O(n log(n))
Invented by Sir Charles Antony Richard Hoare in 1959/1960.
He is a British computer scientist commonly known for inventing the null reference pointer in 1965.
- Take an element in the array and refer to it as the "pivot." For simplicity, we'll take the first element in the array to be the pivot. (As you'll see, this is a bad choice if the array is already sorted. It makes the algorithm a little easier to reason about though, so we'll take the tradeoff.)
- Compare every other element to the pivot. If it's less than the pivot value, move it to the left of the pivot. If it's greater, move it to the right. Don't worry about where on the left or right you're putting these values; the only thing that matters is comparisons to the pivot.
- Once you're done, the pivot will be in the right place, and you can then recursively repeat this process with the left and right halves of the array.
<iframe class="stretch" src="http://visualgo.net/sorting"></iframe>
function quickSort(arr) {
/* 1. If the length of the array is less than 2, it is already sorted, so return it.
2. Otherwise, create two empty arrays (one for the left and one for the right), and set the first value in arr equal to the pivot.
3. Compare every element in the array to the pivot. If the element is less than the pivot, push it into the left array. Otherwise, push it into the right array.
4. Recrusively call quickSort on the left array and the right array, then concatenate these arrays together with the pivot value in between them, and return this larger array. */
}
The downside to the new array approach, is that is uses more memory.
We can implement quick sort in place with a helper function partition
.
// left and right indicate the left and rightmost indices in the sub-array that you're partitioning.
function partition(arr, left, right) {
// 1. Set the pivot value to be the value at the left index, and set a variable called partitionIndex equal to left.
// The partitionIndex will help us keep track of where to perform our swaps so that we wind up with values correctly placed on either side of the pivot.
// 2. For every index greater than left and less than right + 1, compare the array value to the pivot value.
// 3. If the array value at the given index is less than the pivot value,
//increment the partition index and swap the array value with the value at the partition index.
// 4. At the end, swap the pivot value with the value at the partition index
//(this ensures that the pivot ends up in between values less than it and values greater than it).
// 5. Return the partition index.
}
function quickSort(arr, left=0, right=arr.length - 1) {
// 1. If left is less than right, declare a variable called partitionIndex
// which is equal to the result of a call to partition, passing in arr, left, and right.
// After the call to partition, perform a quicksort to the two subarrays to the left and right of the partitionIndex.
// 2. Return arr.
}
n iterations to choose a pivot.
Best case log(n) iterations to partition around each chosen pivot. Worst case n iterations to partition around each chosen pivot.
O(n) * O(log n) = O(n log(n))
O(n) * O(n) = O(n²)
- Implement a merge sort algorithm in Javascript
- Analyze the Big O of merge sort
- Implement a quicksort algorithm in Javascript
- Analyze the Big O of quicksort