Skip to content

Commit c8becaf

Browse files
committed
Add quick sort.
1 parent f29bcab commit c8becaf

File tree

4 files changed

+133
-0
lines changed

4 files changed

+133
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
* [Insertion Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/insertion-sort)
3737
* [Heap Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/heap-sort)
3838
* [Merge Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort)
39+
* [Quick Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort)
3940

4041
## Running Tests
4142

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import Sort from '../Sort';
2+
3+
export default class QuickSort extends Sort {
4+
sort(originalArray) {
5+
// Clone original array to prevent it from modification.
6+
const array = originalArray.slice(0);
7+
8+
// If array has less then or equal to one elements then it is already sorted.
9+
if (array.length <= 1) {
10+
return array;
11+
}
12+
13+
// Init left and right arrays.
14+
const leftArray = [];
15+
const rightArray = [];
16+
17+
// Take the first element of array as a pivot.
18+
const pivotElement = array.shift();
19+
const centerArray = [pivotElement];
20+
21+
// Split all array elements between left, center and right arrays.
22+
while (array.length) {
23+
const currentElement = array.shift();
24+
25+
// Call visiting callback.
26+
this.callbacks.visitingCallback(currentElement);
27+
28+
if (this.comparator.equal(currentElement, pivotElement)) {
29+
centerArray.push(currentElement);
30+
} else if (this.comparator.lessThen(currentElement, pivotElement)) {
31+
leftArray.push(currentElement);
32+
} else {
33+
rightArray.push(currentElement);
34+
}
35+
}
36+
37+
// Sort left and right arrays.
38+
const leftArraySorted = this.sort(leftArray);
39+
const rightArraySorted = this.sort(rightArray);
40+
41+
// Let's now join sorted left array with center array and with sorted right array.
42+
return leftArraySorted.concat(centerArray, rightArraySorted);
43+
}
44+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Quicksort
2+
3+
Quicksort is a divide and conquer algorithm.
4+
Quicksort first divides a large array into two smaller
5+
sub-arrays: the low elements and the high elements.
6+
Quicksort can then recursively sort the sub-arrays
7+
8+
The steps are:
9+
10+
1. Pick an element, called a pivot, from the array.
11+
2. Partitioning: reorder the array so that all elements with
12+
values less than the pivot come before the pivot, while all
13+
elements with values greater than the pivot come after it
14+
(equal values can go either way). After this partitioning,
15+
the pivot is in its final position. This is called the
16+
partition operation.
17+
3. Recursively apply the above steps to the sub-array of
18+
elements with smaller values and separately to the
19+
sub-array of elements with greater values.
20+
21+
Animated visualization of the quicksort algorithm.
22+
The horizontal lines are pivot values.
23+
24+
![Quicksort](https://upload.wikimedia.org/wikipedia/commons/6/6a/Sorting_quicksort_anim.gif)
25+
26+
## References
27+
28+
[Wikipedia](https://en.wikipedia.org/wiki/Quicksort)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import QuickSort from '../QuickSort';
2+
import {
3+
equalArr,
4+
notSortedArr,
5+
reverseArr,
6+
sortedArr,
7+
SortTester,
8+
} from '../../SortTester';
9+
10+
// Complexity constants.
11+
const SORTED_ARRAY_VISITING_COUNT = 190;
12+
const NOT_SORTED_ARRAY_VISITING_COUNT = 62;
13+
const REVERSE_SORTED_ARRAY_VISITING_COUNT = 190;
14+
const EQUAL_ARRAY_VISITING_COUNT = 19;
15+
16+
describe('QuickSort', () => {
17+
it('should sort array', () => {
18+
SortTester.testSort(QuickSort);
19+
});
20+
21+
it('should sort array with custom comparator', () => {
22+
SortTester.testSortWithCustomComparator(QuickSort);
23+
});
24+
25+
it('should do stable sorting', () => {
26+
SortTester.testSortStability(QuickSort);
27+
});
28+
29+
it('should visit EQUAL array element specified number of times', () => {
30+
SortTester.testAlgorithmTimeComplexity(
31+
QuickSort,
32+
equalArr,
33+
EQUAL_ARRAY_VISITING_COUNT,
34+
);
35+
});
36+
37+
it('should visit SORTED array element specified number of times', () => {
38+
SortTester.testAlgorithmTimeComplexity(
39+
QuickSort,
40+
sortedArr,
41+
SORTED_ARRAY_VISITING_COUNT,
42+
);
43+
});
44+
45+
it('should visit NOT SORTED array element specified number of times', () => {
46+
SortTester.testAlgorithmTimeComplexity(
47+
QuickSort,
48+
notSortedArr,
49+
NOT_SORTED_ARRAY_VISITING_COUNT,
50+
);
51+
});
52+
53+
it('should visit REVERSE SORTED array element specified number of times', () => {
54+
SortTester.testAlgorithmTimeComplexity(
55+
QuickSort,
56+
reverseArr,
57+
REVERSE_SORTED_ARRAY_VISITING_COUNT,
58+
);
59+
});
60+
});

0 commit comments

Comments
 (0)