Skip to content

Commit a324712

Browse files
author
yavorski
committedOct 27, 2018
Refactor QuickSortInPlace
* Sort in place without copying the orignal input * Remove `recursiveCall` param from `sort` method as not needed anymore * Extract `partitionArray` function to class method * Remove `swap` function - use destructuring instead * Call `visitingCallback` with the right arguments - in this case with `pivot`
1 parent fac2d1f commit a324712

File tree

2 files changed

+43
-61
lines changed

2 files changed

+43
-61
lines changed
 

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

+42-60
Original file line numberDiff line numberDiff line change
@@ -6,73 +6,55 @@ export default class QuickSortInPlace extends Sort {
66
* This process is difficult to describe, but much clearer with a visualization:
77
* @see: http://www.algomation.com/algorithm/quick-sort-visualization
88
*
9-
* @param {*[]} originalArray - Not sorted array.
9+
* @param {*[]} array - Not sorted array.
1010
* @param {number} inputLowIndex
1111
* @param {number} inputHighIndex
12-
* @param {boolean} recursiveCall
13-
* @return {*[]} - Sorted array.
12+
* @return {*[]} array - Sorted array.
1413
*/
15-
sort(
16-
originalArray,
17-
inputLowIndex = 0,
18-
inputHighIndex = originalArray.length - 1,
19-
recursiveCall = false,
20-
) {
21-
// Copies array on initial call, and then sorts in place.
22-
const array = recursiveCall ? originalArray : [...originalArray];
23-
24-
/**
25-
* The partitionArray() operates on the subarray between lowIndex and highIndex, inclusive.
26-
* It arbitrarily chooses the last element in the subarray as the pivot.
27-
* Then, it partially sorts the subarray into elements than are less than the pivot,
28-
* and elements that are greater than or equal to the pivot.
29-
* Each time partitionArray() is executed, the pivot element is in its final sorted position.
30-
*
31-
* @param {number} lowIndex
32-
* @param {number} highIndex
33-
* @return {number}
34-
*/
35-
const partitionArray = (lowIndex, highIndex) => {
36-
/**
37-
* Swaps two elements in array.
38-
* @param {number} leftIndex
39-
* @param {number} rightIndex
40-
*/
41-
const swap = (leftIndex, rightIndex) => {
42-
const temp = array[leftIndex];
43-
array[leftIndex] = array[rightIndex];
44-
array[rightIndex] = temp;
45-
};
46-
47-
const pivot = array[highIndex];
48-
// visitingCallback is used for time-complexity analysis.
49-
this.callbacks.visitingCallback(array[pivot]);
50-
51-
let partitionIndex = lowIndex;
52-
for (let currentIndex = lowIndex; currentIndex < highIndex; currentIndex += 1) {
53-
if (this.comparator.lessThan(array[currentIndex], pivot)) {
54-
swap(partitionIndex, currentIndex);
55-
partitionIndex += 1;
56-
}
57-
}
58-
59-
// The element at the partitionIndex is guaranteed to be greater than or equal to pivot.
60-
// All elements to the left of partitionIndex are guaranteed to be less than pivot.
61-
// Swapping the pivot with the partitionIndex therefore places the pivot in its
62-
// final sorted position.
63-
swap(partitionIndex, highIndex);
64-
65-
return partitionIndex;
66-
};
67-
14+
sort(array, inputLowIndex = 0, inputHighIndex = array.length - 1) {
6815
// Base case is when low and high converge.
6916
if (inputLowIndex < inputHighIndex) {
70-
const partitionIndex = partitionArray(inputLowIndex, inputHighIndex);
71-
const RECURSIVE_CALL = true;
72-
this.sort(array, inputLowIndex, partitionIndex - 1, RECURSIVE_CALL);
73-
this.sort(array, partitionIndex + 1, inputHighIndex, RECURSIVE_CALL);
17+
const partitionIndex = this.partitionArray(array, inputLowIndex, inputHighIndex);
18+
this.sort(array, inputLowIndex, partitionIndex - 1);
19+
this.sort(array, partitionIndex + 1, inputHighIndex);
7420
}
7521

7622
return array;
7723
}
24+
25+
/**
26+
* The partitionArray() operates on the subarray between lowIndex and highIndex, inclusive.
27+
* It arbitrarily chooses the last element in the subarray as the pivot.
28+
* Then, it partially sorts the subarray into elements than are less than the pivot,
29+
* and elements that are greater than or equal to the pivot.
30+
* Each time partitionArray() is executed, the pivot element is in its final sorted position.
31+
*
32+
* @param {*[]} array - Array for partitioning
33+
* @param {number} lowIndex
34+
* @param {number} highIndex
35+
* @return {number} - Partition index
36+
*/
37+
partitionArray(array, lowIndex, highIndex) {
38+
const pivot = array[highIndex];
39+
40+
// visitingCallback is used for time-complexity analysis.
41+
this.callbacks.visitingCallback(pivot);
42+
43+
let partitionIndex = lowIndex;
44+
for (let currentIndex = lowIndex; currentIndex < highIndex; currentIndex += 1) {
45+
if (this.comparator.lessThan(array[currentIndex], pivot)) {
46+
/* eslint no-param-reassign: ["error", { "props": false }] */
47+
[array[partitionIndex], array[currentIndex]] = [array[currentIndex], array[partitionIndex]];
48+
partitionIndex += 1;
49+
}
50+
}
51+
52+
// The element at the partitionIndex is guaranteed to be greater than or equal to pivot.
53+
// All elements to the left of partitionIndex are guaranteed to be less than pivot.
54+
// Swapping the pivot with the partitionIndex therefore places the pivot in its
55+
// final sorted position.
56+
[array[partitionIndex], array[highIndex]] = [array[highIndex], array[partitionIndex]];
57+
58+
return partitionIndex;
59+
}
7860
}

‎src/algorithms/sorting/quick-sort/__test__/QuickSortInPlace.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99

1010
// Complexity constants.
1111
const SORTED_ARRAY_VISITING_COUNT = 19;
12-
const NOT_SORTED_ARRAY_VISITING_COUNT = 12;
12+
const NOT_SORTED_ARRAY_VISITING_COUNT = 19;
1313
const REVERSE_SORTED_ARRAY_VISITING_COUNT = 19;
1414
const EQUAL_ARRAY_VISITING_COUNT = 19;
1515

0 commit comments

Comments
 (0)
Please sign in to comment.