@@ -11,12 +11,21 @@ export default class QuickSortInPlace extends Sort {
11
11
* @param {number } inputHighIndex
12
12
* @return {*[] }
13
13
*/
14
- sort ( originalArray , inputLowIndex , inputHighIndex ) {
15
- // Destructures array on initial passthrough, and then sorts in place.
16
- const array = inputLowIndex === undefined ? [ ...originalArray ] : originalArray ;
14
+ sort (
15
+ originalArray ,
16
+ inputLowIndex = 0 ,
17
+ inputHighIndex = originalArray . length - 1 ,
18
+ recursiveCall = false ,
19
+ ) {
20
+ // Copies array on initial call, and then sorts in place.
21
+ const array = recursiveCall ? originalArray : [ ...originalArray ] ;
17
22
18
23
/**
19
- * Partition array segment and return index of last swap
24
+ * `partition` operates on the subarray between lowIndex and highIndex, inclusive.
25
+ * it arbitrarily chooses the last element in the subarray as the pivot.
26
+ * then, it partially sorts the subarray into elements than are less than the pivot,
27
+ * and elements that are greater than or equal to the pivot.
28
+ * each time `partition` is executed, the pivot element is in its final sorted position.
20
29
*
21
30
* @param {number } lowIndex
22
31
* @param {number } highIndex
@@ -28,47 +37,38 @@ export default class QuickSortInPlace extends Sort {
28
37
* @param {number } rightIndex
29
38
*/
30
39
const swap = ( leftIndex , rightIndex ) => {
31
- const tempVariable = array [ leftIndex ] ;
40
+ const temp = array [ leftIndex ] ;
32
41
array [ leftIndex ] = array [ rightIndex ] ;
33
- array [ rightIndex ] = tempVariable ;
42
+ array [ rightIndex ] = temp ;
34
43
} ;
35
44
36
45
const pivot = array [ highIndex ] ;
46
+ // visitingCallback is used for time-complexity analysis
37
47
this . callbacks . visitingCallback ( array [ pivot ] ) ;
38
48
39
- let firstRunner = lowIndex - 1 ;
40
- for ( let secondRunner = lowIndex ; secondRunner < highIndex ; secondRunner += 1 ) {
41
- if ( this . comparator . lessThan ( array [ secondRunner ] , pivot ) ) {
42
- firstRunner += 1 ;
43
- swap ( firstRunner , secondRunner ) ;
49
+ let partitionIndex = lowIndex ;
50
+ for ( let currentIndex = lowIndex ; currentIndex < highIndex ; currentIndex += 1 ) {
51
+ if ( this . comparator . lessThan ( array [ currentIndex ] , pivot ) ) {
52
+ swap ( partitionIndex , currentIndex ) ;
53
+ partitionIndex += 1 ;
44
54
}
45
55
}
46
56
47
- if ( this . comparator . lessThan ( pivot , array [ firstRunner + 1 ] ) ) {
48
- swap ( firstRunner + 1 , highIndex ) ;
49
- }
57
+ // The element at the partitionIndex is guaranteed to be greater than or equal to pivot.
58
+ // All elements to the left of partitionIndex are guaranteed to be less than pivot.
59
+ // Swapping the pivot with the partitionIndex therefore places the pivot in its
60
+ // final sorted position.
61
+ swap ( partitionIndex , highIndex ) ;
50
62
51
- return firstRunner + 1 ;
63
+ return partitionIndex ;
52
64
} ;
53
65
54
- /*
55
- * While we can use a default parameter to set `low` to 0, we would
56
- * still have to set `high`'s default within the function as we
57
- * don't have access to `array.length - 1` when declaring parameters
58
- */
59
- const lowIndex = inputLowIndex === undefined ? 0 : inputLowIndex ;
60
- const highIndex = inputHighIndex === undefined ? array . length - 1 : inputHighIndex ;
61
-
62
66
// Base case is when low and high converge
63
- if ( lowIndex < highIndex ) {
64
- const partitionIndex = partition ( lowIndex , highIndex ) ;
65
- /*
66
- * `partition()` swaps elements of the array based on their comparison to the `hi` parameter,
67
- * and then returns the index where swapping is no longer necessary, which can be best thought
68
- * of as the pivot used to split an array in a non-in-place quicksort
69
- */
70
- this . sort ( array , lowIndex , partitionIndex - 1 ) ;
71
- this . sort ( array , partitionIndex + 1 , highIndex ) ;
67
+ if ( inputLowIndex < inputHighIndex ) {
68
+ const partitionIndex = partition ( inputLowIndex , inputHighIndex ) ;
69
+ const RECURSIVE_CALL = true ;
70
+ this . sort ( array , inputLowIndex , partitionIndex - 1 , RECURSIVE_CALL ) ;
71
+ this . sort ( array , partitionIndex + 1 , inputHighIndex , RECURSIVE_CALL ) ;
72
72
}
73
73
74
74
return array ;
0 commit comments