Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bf5d7b3

Browse files
robtaussigtrekhleb
authored andcommitted
Add in-place sort to QuickSort.js (trekhleb#16)
* Add in-place sort to QuickSort.js * Fix linting errors and clean up comments * Change implementation to address lint errors * Trailing space and undefined variable * Create own class for in-place quicksort and use tests * Add trailing space at end of file * Fix placement of visitedCallback, explain itial destructuring
1 parent f93d12d commit bf5d7b3

File tree

3 files changed

+116
-1
lines changed

3 files changed

+116
-1
lines changed

‎src/algorithms/sorting/quick-sort/QuickSort.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export default class QuickSort extends Sort {
55
// Clone original array to prevent it from modification.
66
const array = [...originalArray];
77

8-
// If array has less then or equal to one elements then it is already sorted.
8+
// If array has less than or equal to one elements then it is already sorted.
99
if (array.length <= 1) {
1010
return array;
1111
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import Sort from '../Sort';
2+
3+
export default class QuickSortInPlace extends Sort {
4+
/* Sorting in place avoids unnecessary use of additional memory, but modifies input array.
5+
*
6+
* This process is difficult to describe, but much clearer with a visualization:
7+
* http://www.algomation.com/algorithm/quick-sort-visualization
8+
*/
9+
sort(originalArray, inputLow, inputHigh) {
10+
// Destructures array on initial passthrough, and then sorts in place.
11+
const array = inputLow === undefined ? [...originalArray] : originalArray;
12+
// Partition array segment and return index of last swap
13+
const partition = (l, h) => {
14+
const swap = (left, right) => {
15+
const tempVariable = array[left];
16+
array[left] = array[right];
17+
array[right] = tempVariable;
18+
};
19+
20+
const pivot = array[h];
21+
this.callbacks.visitingCallback(array[pivot]);
22+
let firstRunner = l - 1;
23+
24+
for (let secondRunner = l; secondRunner < h; secondRunner += 1) {
25+
if (this.comparator.lessThan(array[secondRunner], pivot)) {
26+
firstRunner += 1;
27+
swap(firstRunner, secondRunner);
28+
}
29+
}
30+
31+
if (this.comparator.lessThan(pivot, array[firstRunner + 1])) {
32+
swap(firstRunner + 1, h);
33+
}
34+
35+
return firstRunner + 1;
36+
};
37+
38+
/*
39+
* While we can use a default parameter to set `low` to 0, we would
40+
* still have to set `high`'s default within the function as we
41+
* don't have access to `array.length - 1` when declaring paramaters
42+
*/
43+
const low = inputLow === undefined ? 0 : inputLow;
44+
const high = inputHigh === undefined ? array.length - 1 : inputHigh;
45+
46+
// Base case is when low and high converge
47+
if (low < high) {
48+
const partitionIndex = partition(low, high);
49+
/*
50+
* `partition()` swaps elements of the array based on their comparison to the `hi` parameter,
51+
* and then returns the index where swapping is no longer necessary, which can be best thought
52+
* of as the pivot used to split an array in a non-in-place quicksort
53+
*/
54+
this.sort(array, low, partitionIndex - 1);
55+
this.sort(array, partitionIndex + 1, high);
56+
}
57+
return array;
58+
}
59+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import QuickSortInPlace from '../QuickSortInPlace';
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 = 19;
12+
const NOT_SORTED_ARRAY_VISITING_COUNT = 12;
13+
const REVERSE_SORTED_ARRAY_VISITING_COUNT = 19;
14+
const EQUAL_ARRAY_VISITING_COUNT = 19;
15+
16+
describe('QuickSortInPlace', () => {
17+
it('should sort array', () => {
18+
SortTester.testSort(QuickSortInPlace);
19+
});
20+
21+
it('should sort array with custom comparator', () => {
22+
SortTester.testSortWithCustomComparator(QuickSortInPlace);
23+
});
24+
25+
it('should visit EQUAL array element specified number of times', () => {
26+
SortTester.testAlgorithmTimeComplexity(
27+
QuickSortInPlace,
28+
equalArr,
29+
EQUAL_ARRAY_VISITING_COUNT,
30+
);
31+
});
32+
33+
it('should visit SORTED array element specified number of times', () => {
34+
SortTester.testAlgorithmTimeComplexity(
35+
QuickSortInPlace,
36+
sortedArr,
37+
SORTED_ARRAY_VISITING_COUNT,
38+
);
39+
});
40+
41+
it('should visit NOT SORTED array element specified number of times', () => {
42+
SortTester.testAlgorithmTimeComplexity(
43+
QuickSortInPlace,
44+
notSortedArr,
45+
NOT_SORTED_ARRAY_VISITING_COUNT,
46+
);
47+
});
48+
49+
it('should visit REVERSE SORTED array element specified number of times', () => {
50+
SortTester.testAlgorithmTimeComplexity(
51+
QuickSortInPlace,
52+
reverseArr,
53+
REVERSE_SORTED_ARRAY_VISITING_COUNT,
54+
);
55+
});
56+
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /