Add insertion sort.

This commit is contained in:
Oleksii Trekhleb
2018-04-13 07:49:47 +03:00
parent 37bbc53bf3
commit b0247a5baa
8 changed files with 125 additions and 8 deletions

View File

@ -33,6 +33,7 @@
* Sorting
* [Bubble Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/bubble-sort)
* [Selection Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/selection-sort)
* [Insertion Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/insertion-sort)
## Running Tests
@ -98,4 +99,5 @@ Source: [Big O Cheat Sheet](http://bigocheatsheet.com/).
| Name | Best | Average | Worst | Memory | Stable | Method | Notes |
| --------------------- | :-----: | :-------: | :-----: | :-------: | :-------: | :------------ | :-------------- |
| **Bubble sort** | n | n^2 | n^2 | 1 | Yes | Exchanging | Tiny code size |
| **Insertion sort** | n | n^2 | n^2 | 1 | Yes | Insertion | O(n + d), in the worst case over sequences that have d inversions |
| **Selection sort** | n^2 | n^2 | n^2 | 1 | No | Selection | Stable with O(n) extra space, for example using lists |

View File

@ -10,6 +10,9 @@ export default class BubbleSort extends Sort {
for (let i = 0; i < array.length; i += 1) {
swapped = false;
// Call visiting callback.
this.callbacks.visitingCallback(array[i]);
for (let j = 0; j < array.length - 1; j += 1) {
// Call visiting callback.
this.callbacks.visitingCallback(array[j]);

View File

@ -21,7 +21,7 @@ describe('BubbleSort', () => {
});
it('should visit EQUAL array element specified number of times', () => {
const expectedNumberOfVisits = 19;
const expectedNumberOfVisits = 20;
SortTester.testAlgorithmTimeComplexity(
BubbleSort,
@ -31,7 +31,7 @@ describe('BubbleSort', () => {
});
it('should visit SORTED array element specified number of times', () => {
const expectedNumberOfVisits = 19;
const expectedNumberOfVisits = 20;
SortTester.testAlgorithmTimeComplexity(
BubbleSort,
@ -41,7 +41,7 @@ describe('BubbleSort', () => {
});
it('should visit NOT SORTED array element specified number of times', () => {
const expectedNumberOfVisits = 266;
const expectedNumberOfVisits = 280;
SortTester.testAlgorithmTimeComplexity(
BubbleSort,
@ -51,7 +51,7 @@ describe('BubbleSort', () => {
});
it('should visit REVERSE SORTED array element specified number of times', () => {
const expectedNumberOfVisits = 380;
const expectedNumberOfVisits = 400;
SortTester.testAlgorithmTimeComplexity(
BubbleSort,

View File

@ -0,0 +1,35 @@
import Sort from '../Sort';
export default class InsertionSort extends Sort {
sort(originalArray) {
const array = originalArray.slice(0);
// Go through all array elements...
for (let i = 0; i < array.length; i += 1) {
let currentIndex = i;
// Call visiting callback.
this.callbacks.visitingCallback(array[i]);
// Go and check if previous elements and greater then current one.
// If this is the case then swap that elements.
while (
array[currentIndex - 1] &&
this.comparator.lessThen(array[currentIndex], array[currentIndex - 1])
) {
// Call visiting callback.
this.callbacks.visitingCallback(array[currentIndex - 1]);
// Swap the elements.
const tmp = array[currentIndex - 1];
array[currentIndex - 1] = array[currentIndex];
array[currentIndex] = tmp;
// Shift current index left.
currentIndex -= 1;
}
}
return array;
}
}

View File

@ -0,0 +1,12 @@
# Insertion Sort
Insertion sort is a simple sorting algorithm that builds
the final sorted array (or list) one item at a time.
It is much less efficient on large lists than more
advanced algorithms such as quicksort, heapsort, or merge
sort.
![Algorithm Visualization](https://upload.wikimedia.org/wikipedia/commons/4/42/Insertion_sort.gif)
![Algorithm Visualization](https://upload.wikimedia.org/wikipedia/commons/0/0f/Insertion-sort-example-300px.gif)

View File

@ -0,0 +1,62 @@
import InsertionSort from '../InsertionSort';
import {
equalArr,
notSortedArr,
reverseArr,
sortedArr,
SortTester,
} from '../../SortTester';
describe('InsertionSort', () => {
it('should sort array', () => {
SortTester.testSort(InsertionSort);
});
it('should sort array with custom comparator', () => {
SortTester.testSortWithCustomComparator(InsertionSort);
});
it('should do stable sorting', () => {
SortTester.testSortStability(InsertionSort);
});
it('should visit EQUAL array element specified number of times', () => {
const expectedNumberOfVisits = 20;
SortTester.testAlgorithmTimeComplexity(
InsertionSort,
equalArr,
expectedNumberOfVisits,
);
});
it('should visit SORTED array element specified number of times', () => {
const expectedNumberOfVisits = 20;
SortTester.testAlgorithmTimeComplexity(
InsertionSort,
sortedArr,
expectedNumberOfVisits,
);
});
it('should visit NOT SORTED array element specified number of times', () => {
const expectedNumberOfVisits = 101;
SortTester.testAlgorithmTimeComplexity(
InsertionSort,
notSortedArr,
expectedNumberOfVisits,
);
});
it('should visit REVERSE SORTED array element specified number of times', () => {
const expectedNumberOfVisits = 210;
SortTester.testAlgorithmTimeComplexity(
InsertionSort,
reverseArr,
expectedNumberOfVisits,
);
});
});

View File

@ -8,6 +8,9 @@ export default class SelectionSort extends Sort {
for (let i = 0; i < array.length - 1; i += 1) {
let minIndex = i;
// Call visiting callback.
this.callbacks.visitingCallback(array[i]);
// Find minimum element in the rest of array.
for (let j = i + 1; j < array.length; j += 1) {
// Call visiting callback.

View File

@ -17,7 +17,7 @@ describe('SelectionSort', () => {
});
it('should visit EQUAL array element specified number of times', () => {
const expectedNumberOfVisits = 190;
const expectedNumberOfVisits = 209;
SortTester.testAlgorithmTimeComplexity(
SelectionSort,
@ -27,7 +27,7 @@ describe('SelectionSort', () => {
});
it('should visit SORTED array element specified number of times', () => {
const expectedNumberOfVisits = 190;
const expectedNumberOfVisits = 209;
SortTester.testAlgorithmTimeComplexity(
SelectionSort,
@ -37,7 +37,7 @@ describe('SelectionSort', () => {
});
it('should visit NOT SORTED array element specified number of times', () => {
const expectedNumberOfVisits = 190;
const expectedNumberOfVisits = 209;
SortTester.testAlgorithmTimeComplexity(
SelectionSort,
@ -47,7 +47,7 @@ describe('SelectionSort', () => {
});
it('should visit REVERSE SORTED array element specified number of times', () => {
const expectedNumberOfVisits = 190;
const expectedNumberOfVisits = 209;
SortTester.testAlgorithmTimeComplexity(
SelectionSort,