Sorting
We usually sort elements in accending order. A sorting algorithm can have the following proerties:
- Stable: Elements with the same value appear in the same order in the sorted list.
- In place: The algorithm uses a constant amount () of extra memory.
- Non Comparative: The algorithm doesn't compare elements.
The minimum number of comparisons required to sort an array of elements in the worse case (can't assume sorted) is
Algorithms
For each element, find the minimum value in the subarray after it (including itself), and swap it with the current element.
Time Complexity:
For each element with index i, for elements in array till before the element , check if current element is greater than the next, and swap if true. Repeat until no swaps are made for an element.
Time Complexity:
For each element, for each previous element, if current element smaller than current previous element, swap them.
Time Complexity:
Notes: Efficient for small datasets and nearly sorted arrays. for when the array is already sorted.
A divide-and-conquer algorithm that breaks the array into subarrays, sorts them, and merges them back.
- Base case: Array length is less than 2, return array.
- Recursion: Split the array into halves and (merge)sort them.
- Merge the sorted arrays using a helper function, which:
- Create result array
- Until one array ran out of elements, compare foremost element in each array, add smaller to list, and increment index.
- Add remaining elements to the result array.
Time Complexity:
Space Complexity:
Notes: The array is divided into halves, so the time complexity is for the number of divisions and for the merge step.
- Performs better than simple sorts.
- Requires extra space as it doesn't sort in place
The process of rearranging the array so that all elements with values less than the pivot come before the pivot, and all elements with values greater than the pivot come after it.
- Pick index as pivot
- Initialze swap index as -1
- For each element, if element pivot, increment swap, and swap current element with swap index.
- Pivot element is at . Move it to the pivot index by swapping.
- Return pivot index.
Time Complexity:
A divide-and-conquer algorithm that picks a pivot, partitions the array, and recursively sorts the subarrays.
- Base case: Array length is less than 2
- Get pivot index by paritioning array (randomly)
- Recursion: Split and sort the sub-arrays according to pivot index.
Time Complexity:
Space Complexity: (recursion call stack)
Notes: The time complexity depends on the pivot selection. Worst case is when the pivot is the smallest or largest element, as the array is not divided.
The pivot can be selected in different ways:
- Randomized quicksort: Randomly select a pivot.
- Median of three: Select the median of the first, middle, and last element.
- First / middle / last element: Select the first, middle, or last element as the pivot.
If we choose randomized quicksort, the expected time complexity must be , as we don't expect to choose the largest / smallest element every parition.
Call create_max_heap on the array, then for each element from the right, swap the first element with the current element, then call heapify on the array excluding the current element.
Time Complexity: .
Notes:
- Both functions convert an array into a max heap, where the first element must be the largest. This is why we swap the first element with the current element.
- create_max_heap is , and heapify is , which is ran times for each element.
- Heapify is used to maintain the heap property, so it is more efficient as it assumes the array is already a heap.
A stable, non-comparative sorting algorithm.
- Create a new counter array of length (max element in array / number of distinct elements).
- For each element, increment the counter array at the index of the element.
- Then, for each counter item, add their previous value to the current value.
- Create a new result array of length .
- For each element in the original array, add it to the result array at the index of the counter array, then decrement the counter array.
Time Complexity:
Space Complexity: , as we need a counter array of length and a result array of length .
Notes: The algorithm is stable as it loops through the original array at the end in order.
Find the maximum number of digits in the array, then sort the array using exp counting sort for each digit.
Instead of using the element value as the key, we use the ith digit (0-based) by .
Time Complexity:
Space Complexity:
Notes: The algorithm is stable as counting sort is stable. Radix sort works best for arrays with elements with fixed length .
Summary
Algorithm | Average Time | Special Time | Space | Stable | Use when | Ex |
---|---|---|---|---|---|---|
Selection Sort | - | N | - | e | ||
Bubble Sort | Y | Nearly sorted data | e | |||
Insertion Sort | Y | Nearly sorted data | e | |||
Heap Sort | - | N | Limited space | e | ||
Merge Sort | - | Y | Stable | e | ||
Randomized Quick Sort | - | N | Best performance | e | ||
Quick Sort | N | - | e | |||
Counting Sort | - | Y | Small range of integers | e | ||
Radix Sort | - | Y | Fixed-length integers | e |
K-sorted arrays
k-sorted arrays are arrays where each element is at most positions away from its sorted position.
For each element, find the minimum value within the next elements after (including itself), and swap it with the current element.
Time complexity:
- Put the first elements of each array into a min-heap.
- For each remaining element, pop the min element from heap back to array from the start, then add current to the heap.
- Pop remaining elements to array.
Time complexity: time as the heap always has at most elements, and we processed all elements to the heap.
Space complexity: as the heap always has at most elements, and we used the original array as we process the remaining elements.
Other related non-sorting algorithms
A selection algorithm that selects the th smallest element in an unordered list.
- Base case: One element only, return it.
- Get pivot index by paritioning array (randomly)
- Recursive: Check if pivot index is , return if true
- If not, see if pivot index is less than , then search right subarray, else search left subarray.
Time Complexity: .
Notes: Because the pivot index is already sorted, it must be the th smallest element. But if it's not, we know that the smaller elements are on the left, and larger elements are on the right. If we're unlucky and never get the pivot index as , the base case will eventually be reached.
The algorithm can achieve as we only need to search one side of the array.