mirror of
https://github.com/trekhleb/javascript-algorithms.git
synced 2025-07-06 09:23:18 +08:00
Add insertion sort.
This commit is contained in:
@ -33,6 +33,7 @@
|
|||||||
* Sorting
|
* Sorting
|
||||||
* [Bubble Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/bubble-sort)
|
* [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)
|
* [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
|
## Running Tests
|
||||||
|
|
||||||
@ -98,4 +99,5 @@ Source: [Big O Cheat Sheet](http://bigocheatsheet.com/).
|
|||||||
| Name | Best | Average | Worst | Memory | Stable | Method | Notes |
|
| Name | Best | Average | Worst | Memory | Stable | Method | Notes |
|
||||||
| --------------------- | :-----: | :-------: | :-----: | :-------: | :-------: | :------------ | :-------------- |
|
| --------------------- | :-----: | :-------: | :-----: | :-------: | :-------: | :------------ | :-------------- |
|
||||||
| **Bubble sort** | n | n^2 | n^2 | 1 | Yes | Exchanging | Tiny code size |
|
| **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 |
|
| **Selection sort** | n^2 | n^2 | n^2 | 1 | No | Selection | Stable with O(n) extra space, for example using lists |
|
||||||
|
@ -10,6 +10,9 @@ export default class BubbleSort extends Sort {
|
|||||||
for (let i = 0; i < array.length; i += 1) {
|
for (let i = 0; i < array.length; i += 1) {
|
||||||
swapped = false;
|
swapped = false;
|
||||||
|
|
||||||
|
// Call visiting callback.
|
||||||
|
this.callbacks.visitingCallback(array[i]);
|
||||||
|
|
||||||
for (let j = 0; j < array.length - 1; j += 1) {
|
for (let j = 0; j < array.length - 1; j += 1) {
|
||||||
// Call visiting callback.
|
// Call visiting callback.
|
||||||
this.callbacks.visitingCallback(array[j]);
|
this.callbacks.visitingCallback(array[j]);
|
||||||
|
@ -21,7 +21,7 @@ describe('BubbleSort', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should visit EQUAL array element specified number of times', () => {
|
it('should visit EQUAL array element specified number of times', () => {
|
||||||
const expectedNumberOfVisits = 19;
|
const expectedNumberOfVisits = 20;
|
||||||
|
|
||||||
SortTester.testAlgorithmTimeComplexity(
|
SortTester.testAlgorithmTimeComplexity(
|
||||||
BubbleSort,
|
BubbleSort,
|
||||||
@ -31,7 +31,7 @@ describe('BubbleSort', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should visit SORTED array element specified number of times', () => {
|
it('should visit SORTED array element specified number of times', () => {
|
||||||
const expectedNumberOfVisits = 19;
|
const expectedNumberOfVisits = 20;
|
||||||
|
|
||||||
SortTester.testAlgorithmTimeComplexity(
|
SortTester.testAlgorithmTimeComplexity(
|
||||||
BubbleSort,
|
BubbleSort,
|
||||||
@ -41,7 +41,7 @@ describe('BubbleSort', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should visit NOT SORTED array element specified number of times', () => {
|
it('should visit NOT SORTED array element specified number of times', () => {
|
||||||
const expectedNumberOfVisits = 266;
|
const expectedNumberOfVisits = 280;
|
||||||
|
|
||||||
SortTester.testAlgorithmTimeComplexity(
|
SortTester.testAlgorithmTimeComplexity(
|
||||||
BubbleSort,
|
BubbleSort,
|
||||||
@ -51,7 +51,7 @@ describe('BubbleSort', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should visit REVERSE SORTED array element specified number of times', () => {
|
it('should visit REVERSE SORTED array element specified number of times', () => {
|
||||||
const expectedNumberOfVisits = 380;
|
const expectedNumberOfVisits = 400;
|
||||||
|
|
||||||
SortTester.testAlgorithmTimeComplexity(
|
SortTester.testAlgorithmTimeComplexity(
|
||||||
BubbleSort,
|
BubbleSort,
|
||||||
|
35
src/algorithms/sorting/insertion-sort/InsertionSort.js
Normal file
35
src/algorithms/sorting/insertion-sort/InsertionSort.js
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
12
src/algorithms/sorting/insertion-sort/README.md
Normal file
12
src/algorithms/sorting/insertion-sort/README.md
Normal 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
@ -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,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -8,6 +8,9 @@ export default class SelectionSort extends Sort {
|
|||||||
for (let i = 0; i < array.length - 1; i += 1) {
|
for (let i = 0; i < array.length - 1; i += 1) {
|
||||||
let minIndex = i;
|
let minIndex = i;
|
||||||
|
|
||||||
|
// Call visiting callback.
|
||||||
|
this.callbacks.visitingCallback(array[i]);
|
||||||
|
|
||||||
// Find minimum element in the rest of array.
|
// Find minimum element in the rest of array.
|
||||||
for (let j = i + 1; j < array.length; j += 1) {
|
for (let j = i + 1; j < array.length; j += 1) {
|
||||||
// Call visiting callback.
|
// Call visiting callback.
|
||||||
|
@ -17,7 +17,7 @@ describe('SelectionSort', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should visit EQUAL array element specified number of times', () => {
|
it('should visit EQUAL array element specified number of times', () => {
|
||||||
const expectedNumberOfVisits = 190;
|
const expectedNumberOfVisits = 209;
|
||||||
|
|
||||||
SortTester.testAlgorithmTimeComplexity(
|
SortTester.testAlgorithmTimeComplexity(
|
||||||
SelectionSort,
|
SelectionSort,
|
||||||
@ -27,7 +27,7 @@ describe('SelectionSort', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should visit SORTED array element specified number of times', () => {
|
it('should visit SORTED array element specified number of times', () => {
|
||||||
const expectedNumberOfVisits = 190;
|
const expectedNumberOfVisits = 209;
|
||||||
|
|
||||||
SortTester.testAlgorithmTimeComplexity(
|
SortTester.testAlgorithmTimeComplexity(
|
||||||
SelectionSort,
|
SelectionSort,
|
||||||
@ -37,7 +37,7 @@ describe('SelectionSort', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should visit NOT SORTED array element specified number of times', () => {
|
it('should visit NOT SORTED array element specified number of times', () => {
|
||||||
const expectedNumberOfVisits = 190;
|
const expectedNumberOfVisits = 209;
|
||||||
|
|
||||||
SortTester.testAlgorithmTimeComplexity(
|
SortTester.testAlgorithmTimeComplexity(
|
||||||
SelectionSort,
|
SelectionSort,
|
||||||
@ -47,7 +47,7 @@ describe('SelectionSort', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should visit REVERSE SORTED array element specified number of times', () => {
|
it('should visit REVERSE SORTED array element specified number of times', () => {
|
||||||
const expectedNumberOfVisits = 190;
|
const expectedNumberOfVisits = 209;
|
||||||
|
|
||||||
SortTester.testAlgorithmTimeComplexity(
|
SortTester.testAlgorithmTimeComplexity(
|
||||||
SelectionSort,
|
SelectionSort,
|
||||||
|
Reference in New Issue
Block a user