About the #sorting-algorithms series
The #sorting-algorithms series is a collection of posts about reimplemented sorting algorithms in JavaScript.
If you are not familiar with sorting algorithms, a quick introduction and the full list of reimplemented sorting algorithms can be found in the introduction post of the series on sorting algorithms in JavaScript.
If you feel comfortable with the concept of each sorting algorithm and only want to see the code, have a look at the summary post of the series. It removes all explanations and contains only the JavaScript code for all sorting algorithms discussed in the series.
Get the code on Github
Of course, all the code can also be found on Github in the repository sorting-algorithms-in-javascript.
A good way to compare all of them
Unlike the data structures, all sorting algorithms have the same goal and they can all take the same input data. So, for every sorting algorithms of the series, we are going sort an array
of 10 numbers from 1 to 10.
By doing so we will be able to compare the different sorting algorithms more easily. Sorting algorithms are very sensitive to the input data so we will also try different input data to see how they affect the performances.
The Insertion sort algorithm
Definition
Insertion sort algorithm iterates, consuming one input element each repetition, and growing a sorted output list. Each iteration removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. It repeats until no input elements remain. From Wikipedia
This algorithm is often compared to how as human we would sort a card game for example.
Visualization
If you want to have a nice visualization of the algorithm, the visualgo.net website is a nice resource. You can play with many parameters and see which part of the algorithm is doing what.
Complexity
Time complexity | ||
---|---|---|
Best | Average | Worst |
O(n) | O(n^2) | O(n^2) |
To get a full overview of the time and space complexity of the Insertion sort algorithm, have a look to this excellent Big O cheat sheet.
The code
For each sorting algorithm, we are going to look at 2 versions of the code. The first one is the final/clean version, the one that you should remember. The second one implements some counters in order to demonstrate the different time complexities depending of the inputs.
Clean version
// array to sort
var array = [9, 2, 5, 6, 4, 3, 7, 10, 1, 8];
function insertionSort(array) {
for(var i = 0; i < array.length; i++) {
var temp = array[i];
var j = i - 1;
while (j >= 0 && array[j] > temp) {
array[j + 1] = array[j];
j--;
}
array[j + 1] = temp;
}
return array;
}
console.log(insertionSort(array)); // => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
Version with counters
// sample of arrays to sort
var arrayRandom = [9, 2, 5, 6, 4, 3, 7, 10, 1, 8];
var arrayOrdered = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var arrayReversed = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
function insertionSort(array) {
var countOuter = 0;
var countInner = 0;
var countSwap = 0;
for(var i = 0; i < array.length; i++) {
countOuter++;
var temp = array[i];
var j = i - 1;
while (j >= 0 && array[j] > temp) {
countInner++;
countSwap++;
array[j + 1] = array[j];
j--;
}
array[j + 1] = temp;
}
console.log('outer:', countOuter, 'inner:', countInner, 'swap:', countSwap);
return array;
}
insertionSort(arrayRandom.slice()); // => outer: 10 inner: 21 swap: 21
insertionSort(arrayOrdered.slice()); // => outer: 10 inner: 0 swap: 0
insertionSort(arrayReversed.slice()); // => outer: 10 inner: 45 swap: 45