Sorting Algorithms
1. Bubble Sort
In each loop, place the largest number on the top, creating a “bubble”
const bubbleSort = (arr) => {
for (let i = arr.length - 1; i > 0; i--) {
let swap = false;
for (let j = 0; j < i; j++) {
if(arr[j] > arr[j + 1]) {
let temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
swap = true;
}
}
if(!swap) break; // breaks out of the loop when the array is sorted before the loop as reached the end
}
return arr;
}
Bubble sort works fast, when the array is nearly sorted, and the not sorted element is relatively large.
2. Selection Sort
In each loop, place the smallest number at the front of the array.
const selectionSort = (arr) => {
for (let i = 0; i < arr.length; i++) {
let min = i;
for (let j = i + 1; j < arr.length; j++) {
if(arr[j] < arr[min]) min = j;
}
if(i !== min) {
let temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
return arr;
};
Quite similar to bubble sort.
3. Insertion Sort
While looping, create a larger left portion that is sorted.
const insertionSort = (arr) => {
for (let i = 1; i < arr.length; i++) { // for each element starting from second
if(arr[i] < arr[i - 1]) { // if element is smaller than previous
for (let j = i; j > 0; j--) { // go through elements to left until the right place is found
if(arr[j] > arr[j - 1]) { // if the right place is found, break loop
break;
} else {
let temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
}
}
}
}
return arr;
}
4. Merge Sort
Exploit the fact that arrays of 0-1 element are always sorted. Break the array into arrays of single elements, and then merge two of such arrays recursively considering the order.
// array merging helper function
const merge = (arr1, arr2) => {
let result = []
let i = 0;
let j = 0;
while(i < arr1.length && j < arr2.length) {
if (arr1[i] > arr2[j]){
result.push(arr2[j]);
j++;
} else if (arr1[i] < arr2[j]) {
result.push(arr1[i]);
i++;
} else {
result.push(arr1[i]);
result.push(arr2[j]);
i++;
j++;
}
}
// if one array is longer and has finished first, concat rest of the other array
result = (arr1.length === i) ? result.concat(arr2.slice(j)) : result.concat(arr1.slice(i));
return result;
}
// split until arrays of 1 element, and come back up merging
const mergeSort = (arr) => {
if(arr.length === 1) return arr;
return merge(mergeSort(arr.slice(0, Math.floor(arr.length / 2))), mergeSort(arr.slice(Math.floor(arr.length / 2))));
}
mergeSort([1,8,3,2,9,5,100, 20, 2103, 245, 5,1])
Time Complexity
The amount of time it takes to split arrays = O(log n) The amount of time it takes to merge while comparing each element = O(n) = O(n log n)
5. Quick Sort
Select a random pivot index in the array, fix the position of that pivot. Then recursively do the same procedure with the left and right side of the pivot.
// finding the pivot's correct place to fix
const pivot = (arr, start=0, end=arr.length-1) => {
let pivotIndex = start;
const pivot = arr[start]
for (let i = start + 1; i <= end; i++) {
if(pivot > arr[i]) {
pivotIndex++;
let temp = arr[pivotIndex];
arr[pivotIndex] = arr[i];
arr[i] = temp;
}
}
let temp = arr[pivotIndex];
arr[pivotIndex] = pivot;
arr[start] = temp;
return pivotIndex;
}
const quickSort = (arr, left = 0, right = arr.length - 1) => {
if(left < right){
let pivotPoint = pivot(arr, left, right);
quickSort(arr, left, pivotPoint - 1)
quickSort(arr, pivotPoint + 1, right)
}
return arr;
}
Time Complexity
In the worst case for quick sort, which is if the array is already sorted, the time complexity is O(n ^ 2)
Decomposing the array n times X Compare n times
6. Radix Sort
Unlike the other sorting methods, radix sort is not a comparison sort, in that it doesn’t sort the array by comparing the size of each element. Using the characteristics of numbers, sort by placing each element into buckets of 0-9 by the digits starting from the one’s place up.
const getDigit = (num, place) => {
return Math.floor(Math.abs(num) / (Math.pow(10, place))) % 10;
}
const digitCount = (num) => {
if(num === 0) return 1;
return Math.floor(Math.log10(Math.abs(num))) + 1;
}
const mostDigits = (arr) => {
let max = 0;
for (let e of arr) {
let currDigit = digitCount(e)
max = (max > currDigit) ? max : currDigit;
}
return max;
}
const radixSort = (arr) => {
const loop = mostDigits(arr);
for(let i = 0; i < loop; i++) {
let buckets = [[],[],[],[],[],[],[],[],[],[]]
for(let e of arr) {
buckets[getDigit(e, i)].push(e);
}
arr = buckets.flat();
}
return arr;
}