From a324712dc3b19a4d9e797ba73f25eb7aade3fbd6 Mon Sep 17 00:00:00 2001
From: yavorski <yaforski@gmail.com>
Date: Sat, 27 Oct 2018 22:03:44 +0300
Subject: [PATCH] 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`
---
 .../sorting/quick-sort/QuickSortInPlace.js    | 102 ++++++++----------
 .../__test__/QuickSortInPlace.test.js         |   2 +-
 2 files changed, 43 insertions(+), 61 deletions(-)

diff --git a/src/algorithms/sorting/quick-sort/QuickSortInPlace.js b/src/algorithms/sorting/quick-sort/QuickSortInPlace.js
index 8bc67577cc..7f8a4b80c9 100644
--- a/src/algorithms/sorting/quick-sort/QuickSortInPlace.js
+++ b/src/algorithms/sorting/quick-sort/QuickSortInPlace.js
@@ -6,73 +6,55 @@ export default class QuickSortInPlace extends Sort {
    * This process is difficult to describe, but much clearer with a visualization:
    * @see: http://www.algomation.com/algorithm/quick-sort-visualization
    *
-   * @param {*[]} originalArray - Not sorted array.
+   * @param {*[]} array - Not sorted array.
    * @param {number} inputLowIndex
    * @param {number} inputHighIndex
-   * @param {boolean} recursiveCall
-   * @return {*[]} - Sorted array.
+   * @return {*[]} array - Sorted array.
    */
-  sort(
-    originalArray,
-    inputLowIndex = 0,
-    inputHighIndex = originalArray.length - 1,
-    recursiveCall = false,
-  ) {
-    // Copies array on initial call, and then sorts in place.
-    const array = recursiveCall ? originalArray : [...originalArray];
-
-    /**
-     * The partitionArray() 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 partitionArray() is executed, the pivot element is in its final sorted position.
-     *
-     * @param {number} lowIndex
-     * @param {number} highIndex
-     * @return {number}
-     */
-    const partitionArray = (lowIndex, highIndex) => {
-      /**
-       * Swaps two elements in array.
-       * @param {number} leftIndex
-       * @param {number} rightIndex
-       */
-      const swap = (leftIndex, rightIndex) => {
-        const temp = array[leftIndex];
-        array[leftIndex] = array[rightIndex];
-        array[rightIndex] = temp;
-      };
-
-      const pivot = array[highIndex];
-      // visitingCallback is used for time-complexity analysis.
-      this.callbacks.visitingCallback(array[pivot]);
-
-      let partitionIndex = lowIndex;
-      for (let currentIndex = lowIndex; currentIndex < highIndex; currentIndex += 1) {
-        if (this.comparator.lessThan(array[currentIndex], pivot)) {
-          swap(partitionIndex, currentIndex);
-          partitionIndex += 1;
-        }
-      }
-
-      // The element at the partitionIndex is guaranteed to be greater than or equal to pivot.
-      // 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 partitionIndex;
-    };
-
+  sort(array, inputLowIndex = 0, inputHighIndex = array.length - 1) {
     // Base case is when low and high converge.
     if (inputLowIndex < inputHighIndex) {
-      const partitionIndex = partitionArray(inputLowIndex, inputHighIndex);
-      const RECURSIVE_CALL = true;
-      this.sort(array, inputLowIndex, partitionIndex - 1, RECURSIVE_CALL);
-      this.sort(array, partitionIndex + 1, inputHighIndex, RECURSIVE_CALL);
+      const partitionIndex = this.partitionArray(array, inputLowIndex, inputHighIndex);
+      this.sort(array, inputLowIndex, partitionIndex - 1);
+      this.sort(array, partitionIndex + 1, inputHighIndex);
     }
 
     return array;
   }
+
+  /**
+   * The partitionArray() 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 partitionArray() is executed, the pivot element is in its final sorted position.
+   *
+   * @param {*[]} array - Array for partitioning
+   * @param {number} lowIndex
+   * @param {number} highIndex
+   * @return {number} - Partition index
+   */
+  partitionArray(array, lowIndex, highIndex) {
+    const pivot = array[highIndex];
+
+    // visitingCallback is used for time-complexity analysis.
+    this.callbacks.visitingCallback(pivot);
+
+    let partitionIndex = lowIndex;
+    for (let currentIndex = lowIndex; currentIndex < highIndex; currentIndex += 1) {
+      if (this.comparator.lessThan(array[currentIndex], pivot)) {
+        /* eslint no-param-reassign: ["error", { "props": false }] */
+        [array[partitionIndex], array[currentIndex]] = [array[currentIndex], array[partitionIndex]];
+        partitionIndex += 1;
+      }
+    }
+
+    // The element at the partitionIndex is guaranteed to be greater than or equal to pivot.
+    // 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.
+    [array[partitionIndex], array[highIndex]] = [array[highIndex], array[partitionIndex]];
+
+    return partitionIndex;
+  }
 }
diff --git a/src/algorithms/sorting/quick-sort/__test__/QuickSortInPlace.test.js b/src/algorithms/sorting/quick-sort/__test__/QuickSortInPlace.test.js
index 0e103f2ef2..bf194d8b6f 100644
--- a/src/algorithms/sorting/quick-sort/__test__/QuickSortInPlace.test.js
+++ b/src/algorithms/sorting/quick-sort/__test__/QuickSortInPlace.test.js
@@ -9,7 +9,7 @@ import {
 
 // Complexity constants.
 const SORTED_ARRAY_VISITING_COUNT = 19;
-const NOT_SORTED_ARRAY_VISITING_COUNT = 12;
+const NOT_SORTED_ARRAY_VISITING_COUNT = 19;
 const REVERSE_SORTED_ARRAY_VISITING_COUNT = 19;
 const EQUAL_ARRAY_VISITING_COUNT = 19;