mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-12-26 07:01:18 +08:00
Minor refactor of QuickSortInPlace for simplification (#187)
This commit is contained in:
parent
92b9e6ad1d
commit
66f19d65c5
@ -11,12 +11,21 @@ export default class QuickSortInPlace extends Sort {
|
|||||||
* @param {number} inputHighIndex
|
* @param {number} inputHighIndex
|
||||||
* @return {*[]}
|
* @return {*[]}
|
||||||
*/
|
*/
|
||||||
sort(originalArray, inputLowIndex, inputHighIndex) {
|
sort(
|
||||||
// Destructures array on initial passthrough, and then sorts in place.
|
originalArray,
|
||||||
const array = inputLowIndex === undefined ? [...originalArray] : originalArray;
|
inputLowIndex = 0,
|
||||||
|
inputHighIndex = originalArray.length - 1,
|
||||||
|
recursiveCall = false,
|
||||||
|
) {
|
||||||
|
// Copies array on initial call, and then sorts in place.
|
||||||
|
const array = recursiveCall ? originalArray : [...originalArray];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Partition array segment and return index of last swap
|
* `partition` operates on the subarray between lowIndex and highIndex, inclusive.
|
||||||
|
* it arbitrarily chooses the last element in the subarray as the pivot.
|
||||||
|
* then, it partially sorts the subarray into elements than are less than the pivot,
|
||||||
|
* and elements that are greater than or equal to the pivot.
|
||||||
|
* each time `partition` is executed, the pivot element is in its final sorted position.
|
||||||
*
|
*
|
||||||
* @param {number} lowIndex
|
* @param {number} lowIndex
|
||||||
* @param {number} highIndex
|
* @param {number} highIndex
|
||||||
@ -28,47 +37,38 @@ export default class QuickSortInPlace extends Sort {
|
|||||||
* @param {number} rightIndex
|
* @param {number} rightIndex
|
||||||
*/
|
*/
|
||||||
const swap = (leftIndex, rightIndex) => {
|
const swap = (leftIndex, rightIndex) => {
|
||||||
const tempVariable = array[leftIndex];
|
const temp = array[leftIndex];
|
||||||
array[leftIndex] = array[rightIndex];
|
array[leftIndex] = array[rightIndex];
|
||||||
array[rightIndex] = tempVariable;
|
array[rightIndex] = temp;
|
||||||
};
|
};
|
||||||
|
|
||||||
const pivot = array[highIndex];
|
const pivot = array[highIndex];
|
||||||
|
// visitingCallback is used for time-complexity analysis
|
||||||
this.callbacks.visitingCallback(array[pivot]);
|
this.callbacks.visitingCallback(array[pivot]);
|
||||||
|
|
||||||
let firstRunner = lowIndex - 1;
|
let partitionIndex = lowIndex;
|
||||||
for (let secondRunner = lowIndex; secondRunner < highIndex; secondRunner += 1) {
|
for (let currentIndex = lowIndex; currentIndex < highIndex; currentIndex += 1) {
|
||||||
if (this.comparator.lessThan(array[secondRunner], pivot)) {
|
if (this.comparator.lessThan(array[currentIndex], pivot)) {
|
||||||
firstRunner += 1;
|
swap(partitionIndex, currentIndex);
|
||||||
swap(firstRunner, secondRunner);
|
partitionIndex += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.comparator.lessThan(pivot, array[firstRunner + 1])) {
|
// The element at the partitionIndex is guaranteed to be greater than or equal to pivot.
|
||||||
swap(firstRunner + 1, highIndex);
|
// All elements to the left of partitionIndex are guaranteed to be less than pivot.
|
||||||
}
|
// Swapping the pivot with the partitionIndex therefore places the pivot in its
|
||||||
|
// final sorted position.
|
||||||
|
swap(partitionIndex, highIndex);
|
||||||
|
|
||||||
return firstRunner + 1;
|
return partitionIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* While we can use a default parameter to set `low` to 0, we would
|
|
||||||
* still have to set `high`'s default within the function as we
|
|
||||||
* don't have access to `array.length - 1` when declaring parameters
|
|
||||||
*/
|
|
||||||
const lowIndex = inputLowIndex === undefined ? 0 : inputLowIndex;
|
|
||||||
const highIndex = inputHighIndex === undefined ? array.length - 1 : inputHighIndex;
|
|
||||||
|
|
||||||
// Base case is when low and high converge
|
// Base case is when low and high converge
|
||||||
if (lowIndex < highIndex) {
|
if (inputLowIndex < inputHighIndex) {
|
||||||
const partitionIndex = partition(lowIndex, highIndex);
|
const partitionIndex = partition(inputLowIndex, inputHighIndex);
|
||||||
/*
|
const RECURSIVE_CALL = true;
|
||||||
* `partition()` swaps elements of the array based on their comparison to the `hi` parameter,
|
this.sort(array, inputLowIndex, partitionIndex - 1, RECURSIVE_CALL);
|
||||||
* and then returns the index where swapping is no longer necessary, which can be best thought
|
this.sort(array, partitionIndex + 1, inputHighIndex, RECURSIVE_CALL);
|
||||||
* of as the pivot used to split an array in a non-in-place quicksort
|
|
||||||
*/
|
|
||||||
this.sort(array, lowIndex, partitionIndex - 1);
|
|
||||||
this.sort(array, partitionIndex + 1, highIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
|
Loading…
Reference in New Issue
Block a user