mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-11-10 11:09:43 +08:00
Add quick sort.
This commit is contained in:
parent
f29bcabffb
commit
c8becaf299
@ -36,6 +36,7 @@
|
||||
* [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)
|
||||
* [Quick Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort)
|
||||
|
||||
## Running Tests
|
||||
|
||||
|
44
src/algorithms/sorting/quick-sort/QuickSort.js
Normal file
44
src/algorithms/sorting/quick-sort/QuickSort.js
Normal file
@ -0,0 +1,44 @@
|
||||
import Sort from '../Sort';
|
||||
|
||||
export default class QuickSort extends Sort {
|
||||
sort(originalArray) {
|
||||
// Clone original array to prevent it from modification.
|
||||
const array = originalArray.slice(0);
|
||||
|
||||
// If array has less then or equal to one elements then it is already sorted.
|
||||
if (array.length <= 1) {
|
||||
return array;
|
||||
}
|
||||
|
||||
// Init left and right arrays.
|
||||
const leftArray = [];
|
||||
const rightArray = [];
|
||||
|
||||
// Take the first element of array as a pivot.
|
||||
const pivotElement = array.shift();
|
||||
const centerArray = [pivotElement];
|
||||
|
||||
// Split all array elements between left, center and right arrays.
|
||||
while (array.length) {
|
||||
const currentElement = array.shift();
|
||||
|
||||
// Call visiting callback.
|
||||
this.callbacks.visitingCallback(currentElement);
|
||||
|
||||
if (this.comparator.equal(currentElement, pivotElement)) {
|
||||
centerArray.push(currentElement);
|
||||
} else if (this.comparator.lessThen(currentElement, pivotElement)) {
|
||||
leftArray.push(currentElement);
|
||||
} else {
|
||||
rightArray.push(currentElement);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort left and right arrays.
|
||||
const leftArraySorted = this.sort(leftArray);
|
||||
const rightArraySorted = this.sort(rightArray);
|
||||
|
||||
// Let's now join sorted left array with center array and with sorted right array.
|
||||
return leftArraySorted.concat(centerArray, rightArraySorted);
|
||||
}
|
||||
}
|
28
src/algorithms/sorting/quick-sort/README.md
Normal file
28
src/algorithms/sorting/quick-sort/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Quicksort
|
||||
|
||||
Quicksort is a divide and conquer algorithm.
|
||||
Quicksort first divides a large array into two smaller
|
||||
sub-arrays: the low elements and the high elements.
|
||||
Quicksort can then recursively sort the sub-arrays
|
||||
|
||||
The steps are:
|
||||
|
||||
1. Pick an element, called a pivot, from the array.
|
||||
2. Partitioning: reorder the array so that all elements with
|
||||
values less than the pivot come before the pivot, while all
|
||||
elements with values greater than the pivot come after it
|
||||
(equal values can go either way). After this partitioning,
|
||||
the pivot is in its final position. This is called the
|
||||
partition operation.
|
||||
3. Recursively apply the above steps to the sub-array of
|
||||
elements with smaller values and separately to the
|
||||
sub-array of elements with greater values.
|
||||
|
||||
Animated visualization of the quicksort algorithm.
|
||||
The horizontal lines are pivot values.
|
||||
|
||||
![Quicksort](https://upload.wikimedia.org/wikipedia/commons/6/6a/Sorting_quicksort_anim.gif)
|
||||
|
||||
## References
|
||||
|
||||
[Wikipedia](https://en.wikipedia.org/wiki/Quicksort)
|
60
src/algorithms/sorting/quick-sort/__test__/QuickSort.test.js
Normal file
60
src/algorithms/sorting/quick-sort/__test__/QuickSort.test.js
Normal file
@ -0,0 +1,60 @@
|
||||
import QuickSort from '../QuickSort';
|
||||
import {
|
||||
equalArr,
|
||||
notSortedArr,
|
||||
reverseArr,
|
||||
sortedArr,
|
||||
SortTester,
|
||||
} from '../../SortTester';
|
||||
|
||||
// Complexity constants.
|
||||
const SORTED_ARRAY_VISITING_COUNT = 190;
|
||||
const NOT_SORTED_ARRAY_VISITING_COUNT = 62;
|
||||
const REVERSE_SORTED_ARRAY_VISITING_COUNT = 190;
|
||||
const EQUAL_ARRAY_VISITING_COUNT = 19;
|
||||
|
||||
describe('QuickSort', () => {
|
||||
it('should sort array', () => {
|
||||
SortTester.testSort(QuickSort);
|
||||
});
|
||||
|
||||
it('should sort array with custom comparator', () => {
|
||||
SortTester.testSortWithCustomComparator(QuickSort);
|
||||
});
|
||||
|
||||
it('should do stable sorting', () => {
|
||||
SortTester.testSortStability(QuickSort);
|
||||
});
|
||||
|
||||
it('should visit EQUAL array element specified number of times', () => {
|
||||
SortTester.testAlgorithmTimeComplexity(
|
||||
QuickSort,
|
||||
equalArr,
|
||||
EQUAL_ARRAY_VISITING_COUNT,
|
||||
);
|
||||
});
|
||||
|
||||
it('should visit SORTED array element specified number of times', () => {
|
||||
SortTester.testAlgorithmTimeComplexity(
|
||||
QuickSort,
|
||||
sortedArr,
|
||||
SORTED_ARRAY_VISITING_COUNT,
|
||||
);
|
||||
});
|
||||
|
||||
it('should visit NOT SORTED array element specified number of times', () => {
|
||||
SortTester.testAlgorithmTimeComplexity(
|
||||
QuickSort,
|
||||
notSortedArr,
|
||||
NOT_SORTED_ARRAY_VISITING_COUNT,
|
||||
);
|
||||
});
|
||||
|
||||
it('should visit REVERSE SORTED array element specified number of times', () => {
|
||||
SortTester.testAlgorithmTimeComplexity(
|
||||
QuickSort,
|
||||
reverseArr,
|
||||
REVERSE_SORTED_ARRAY_VISITING_COUNT,
|
||||
);
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user