mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-11-10 11:09:43 +08:00
Add merge sort.
This commit is contained in:
parent
b17ba61348
commit
ed2abde623
@ -35,6 +35,7 @@
|
||||
* [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)
|
||||
* [Heap Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/heap-sort)
|
||||
* [Merge Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort)
|
||||
|
||||
## Running Tests
|
||||
|
||||
|
@ -32,6 +32,7 @@ export class SortTester {
|
||||
expect(sorter.sort([''])).toEqual(['']);
|
||||
expect(sorter.sort(['a'])).toEqual(['a']);
|
||||
expect(sorter.sort(['aa', 'a'])).toEqual(['a', 'aa']);
|
||||
expect(sorter.sort(['aa', 'q', 'a', 'bbbb', 'ccc'])).toEqual(['q', 'a', 'aa', 'ccc', 'bbbb']);
|
||||
expect(sorter.sort(['aa', 'aa'])).toEqual(['aa', 'aa']);
|
||||
}
|
||||
|
||||
|
59
src/algorithms/sorting/merge-sort/MergeSort.js
Normal file
59
src/algorithms/sorting/merge-sort/MergeSort.js
Normal file
@ -0,0 +1,59 @@
|
||||
import Sort from '../Sort';
|
||||
|
||||
export default class MergeSort extends Sort {
|
||||
sort(originalArray) {
|
||||
// Call visiting callback.
|
||||
this.callbacks.visitingCallback(null);
|
||||
|
||||
// If array is empty or consists of one element then return this array since it is sorted.
|
||||
if (originalArray.length <= 1) {
|
||||
return originalArray;
|
||||
}
|
||||
|
||||
// Split array on two halves.
|
||||
const middleIndex = Math.floor(originalArray.length / 2);
|
||||
const leftArray = originalArray.slice(0, middleIndex);
|
||||
const rightArray = originalArray.slice(middleIndex, originalArray.length);
|
||||
|
||||
// Sort two halves of split array
|
||||
const leftSortedArray = this.sort(leftArray);
|
||||
const rightSortedArray = this.sort(rightArray);
|
||||
|
||||
// Merge two sorted arrays into one.
|
||||
return this.mergeSortedArrays(leftSortedArray, rightSortedArray);
|
||||
}
|
||||
|
||||
mergeSortedArrays(leftArray, rightArray) {
|
||||
let sortedArray = [];
|
||||
|
||||
// In case if arrays are not of size 1.
|
||||
while (leftArray.length && rightArray.length) {
|
||||
let minimumElement = null;
|
||||
|
||||
// Find minimum element of two arrays.
|
||||
if (this.comparator.lessThenOrEqual(leftArray[0], rightArray[0])) {
|
||||
minimumElement = leftArray.shift();
|
||||
} else {
|
||||
minimumElement = rightArray.shift();
|
||||
}
|
||||
|
||||
// Call visiting callback.
|
||||
this.callbacks.visitingCallback(minimumElement);
|
||||
|
||||
// Push the minimum element of two arrays to the sorted array.
|
||||
sortedArray.push(minimumElement);
|
||||
}
|
||||
|
||||
// If one of two array still have elements we need to just concatenate
|
||||
// this element to the sorted array since it is already sorted.
|
||||
if (leftArray.length) {
|
||||
sortedArray = sortedArray.concat(leftArray);
|
||||
}
|
||||
|
||||
if (rightArray.length) {
|
||||
sortedArray = sortedArray.concat(rightArray);
|
||||
}
|
||||
|
||||
return sortedArray;
|
||||
}
|
||||
}
|
27
src/algorithms/sorting/merge-sort/README.md
Normal file
27
src/algorithms/sorting/merge-sort/README.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Merge Sort
|
||||
|
||||
In computer science, merge sort (also commonly spelled
|
||||
mergesort) is an efficient, general-purpose,
|
||||
comparison-based sorting algorithm. Most implementations
|
||||
produce a stable sort, which means that the implementation
|
||||
preserves the input order of equal elements in the sorted
|
||||
output. Mergesort is a divide and conquer algorithm that
|
||||
was invented by John von Neumann in 1945.
|
||||
|
||||
An example of merge sort. First divide the list into
|
||||
the smallest unit (1 element), then compare each
|
||||
element with the adjacent list to sort and merge the
|
||||
two adjacent lists. Finally all the elements are sorted
|
||||
and merged.
|
||||
|
||||
![Merge Sort](https://upload.wikimedia.org/wikipedia/commons/c/cc/Merge-sort-example-300px.gif)
|
||||
|
||||
A recursive merge sort algorithm used to sort an array of 7
|
||||
integer values. These are the steps a human would take to
|
||||
emulate merge sort (top-down).
|
||||
|
||||
![Merge Sort](https://upload.wikimedia.org/wikipedia/commons/e/e6/Merge_sort_algorithm_diagram.svg)
|
||||
|
||||
## References
|
||||
|
||||
[Wikipedia](https://en.wikipedia.org/wiki/Merge_sort)
|
60
src/algorithms/sorting/merge-sort/__test__/MergeSort.test.js
Normal file
60
src/algorithms/sorting/merge-sort/__test__/MergeSort.test.js
Normal file
@ -0,0 +1,60 @@
|
||||
import BubbleSort from '../MergeSort';
|
||||
import {
|
||||
equalArr,
|
||||
notSortedArr,
|
||||
reverseArr,
|
||||
sortedArr,
|
||||
SortTester,
|
||||
} from '../../SortTester';
|
||||
|
||||
// Complexity constants.
|
||||
const SORTED_ARRAY_VISITING_COUNT = 79;
|
||||
const NOT_SORTED_ARRAY_VISITING_COUNT = 102;
|
||||
const REVERSE_SORTED_ARRAY_VISITING_COUNT = 87;
|
||||
const EQUAL_ARRAY_VISITING_COUNT = 79;
|
||||
|
||||
describe('MergeSort', () => {
|
||||
it('should sort array', () => {
|
||||
SortTester.testSort(BubbleSort);
|
||||
});
|
||||
|
||||
it('should sort array with custom comparator', () => {
|
||||
SortTester.testSortWithCustomComparator(BubbleSort);
|
||||
});
|
||||
|
||||
// it('should do stable sorting', () => {
|
||||
// SortTester.testSortStability(BubbleSort);
|
||||
// });
|
||||
|
||||
it('should visit EQUAL array element specified number of times', () => {
|
||||
SortTester.testAlgorithmTimeComplexity(
|
||||
BubbleSort,
|
||||
equalArr,
|
||||
EQUAL_ARRAY_VISITING_COUNT,
|
||||
);
|
||||
});
|
||||
|
||||
it('should visit SORTED array element specified number of times', () => {
|
||||
SortTester.testAlgorithmTimeComplexity(
|
||||
BubbleSort,
|
||||
sortedArr,
|
||||
SORTED_ARRAY_VISITING_COUNT,
|
||||
);
|
||||
});
|
||||
|
||||
it('should visit NOT SORTED array element specified number of times', () => {
|
||||
SortTester.testAlgorithmTimeComplexity(
|
||||
BubbleSort,
|
||||
notSortedArr,
|
||||
NOT_SORTED_ARRAY_VISITING_COUNT,
|
||||
);
|
||||
});
|
||||
|
||||
it('should visit REVERSE SORTED array element specified number of times', () => {
|
||||
SortTester.testAlgorithmTimeComplexity(
|
||||
BubbleSort,
|
||||
reverseArr,
|
||||
REVERSE_SORTED_ARRAY_VISITING_COUNT,
|
||||
);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user