From f53cf76a713bdad5916a7f0259dd8c824869c713 Mon Sep 17 00:00:00 2001 From: Anwar Ahmed Date: Sun, 15 Sep 2024 21:37:24 +0300 Subject: [PATCH 1/3] feat: add function to choose better pivot and interface for the module --- Sorts/QuickSortRecursive.js | 53 +++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/Sorts/QuickSortRecursive.js b/Sorts/QuickSortRecursive.js index e45dc34dac..94aba3aff1 100644 --- a/Sorts/QuickSortRecursive.js +++ b/Sorts/QuickSortRecursive.js @@ -15,22 +15,39 @@ Problem & Source of Explanation => https://www.cs.auckland.ac.nz/software/AlgAnim/qsort1a.html */ + /** - * Partition in place QuickSort. - * @param {number[]} inputList list of values. - * @param {number} low lower index for partition. - * @param {number} high higher index for partition. + * Sorts the input list using the quicksort algorithm. + * + * @param {Array} inputList - the list to be sorted + * @return {Array} the sorted list */ -const quickSort = (inputList, low, high) => { +// encapsulate the main function to to be the interface of our module +const quickSort = (inputList) => { if (!Array.isArray(inputList)) { throw new TypeError('Please input a valid list or array.') } + return quickSortHelper(inputList, 0, inputList.length - 1) +} + + +/** + * Recursively sorts the input list using the quicksort algorithm. + * + * @param {number[]} inputList - the list to be sorted + * @param {number} low - the lower index of the current partition + * @param {number} high - the higher index of the current partition + * @return {number[]} the sorted list + */ + +const quickSortHelper = (inputList, low, high) => { + // base case if (low < high) { // get the partition index. const pIndex = partition(inputList, low, high) // recursively call the quickSort method again. - quickSort(inputList, low, pIndex - 1) - quickSort(inputList, pIndex + 1, high) + quickSortHelper(inputList, low, pIndex - 1) + quickSortHelper(inputList, pIndex + 1, high) } return inputList } @@ -43,7 +60,9 @@ const quickSort = (inputList, low, high) => { * @returns {number} `pIndex` pivot index value. */ const partition = (partitionList, low, high) => { - const pivot = partitionList[high] + let mid =Math.floor((low + high) / 2) + // get the median of three is good technique for partitioning to be sure that the 2 sub-arrays will be almost equal or near + const pivot = medianOfThree(partitionList, low, mid, high) let pIndex = low for (let index = low; index <= high - 1; index++) { if (partitionList[index] < pivot) { @@ -62,4 +81,22 @@ const partition = (partitionList, low, high) => { return pIndex } + +/** + * Returns the median value of three elements in an array. + * + * @param {number[]} arr - the input array + * @param {number} low - the index of the first element + * @param {number} mid - the index of the second element + * @param {number} high - the index of the third element + * @return {number} the median value of the three elements + */ + +const medianOfThree = (partitionList, low,mid, high) => { + const a = partitionList[low], b = partitionList[mid], c = partitionList[high]; + if ((a > b) !== (a > c)) return a; + else if ((b > a) !== (b > c)) return b; + else return c; +} + export { quickSort } From cc0700360ebcbb46a722fecafa939d7baef9adf6 Mon Sep 17 00:00:00 2001 From: Anwar Ahmed Date: Sun, 15 Sep 2024 22:07:48 +0300 Subject: [PATCH 2/3] fix: refactor the test cases with adding interface for the module --- Sorts/test/QuickSortRecursive.test.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Sorts/test/QuickSortRecursive.test.js b/Sorts/test/QuickSortRecursive.test.js index 7516877a11..5e258dce03 100644 --- a/Sorts/test/QuickSortRecursive.test.js +++ b/Sorts/test/QuickSortRecursive.test.js @@ -2,13 +2,13 @@ import { quickSort } from '../QuickSortRecursive' describe('QuickSortRecursive | Partition In Place Method', () => { it('Expectedly, throw some error if we pass a non-array input', () => { - expect(() => quickSort('xyz', 0, 2)).toThrow( + expect(() => quickSort('xyz')).toThrow( 'Please input a valid list or array.' ) - expect(() => quickSort(null, 0, 4)).toThrow( + expect(() => quickSort(null)).toThrow( 'Please input a valid list or array.' ) - expect(() => quickSort(55, 0, 2)).toThrow( + expect(() => quickSort(55)).toThrow( 'Please input a valid list or array.' ) }) @@ -16,7 +16,7 @@ describe('QuickSortRecursive | Partition In Place Method', () => { it('Expectedly, the quickSort method will sort the unsorted list in ascending order', () => { const unSortArray = [5, 9, 3, 4, 6, 2, 0, 1, 7, 8] const sortedExpectedArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - expect(quickSort(unSortArray, 0, unSortArray.length - 1)).toEqual( + expect(quickSort(unSortArray)).toEqual( sortedExpectedArray ) }) @@ -24,7 +24,7 @@ describe('QuickSortRecursive | Partition In Place Method', () => { it('Expectedly, the quickSort method will arrange the list of character values in dictionary order.', () => { const unSortList = ['d', 'e', 'c', 'a', 'f', 'b'] const sortedExpectedList = ['a', 'b', 'c', 'd', 'e', 'f'] - expect(quickSort(unSortList, 0, unSortList.length - 1)).toEqual( + expect(quickSort(unSortList)).toEqual( sortedExpectedList ) }) From e573010e638add00dc63a9b3d83fafdf69d7eeaf Mon Sep 17 00:00:00 2001 From: Anwar Ahmed Date: Tue, 17 Sep 2024 17:25:10 +0300 Subject: [PATCH 3/3] fix: repair style with prettier --- Sorts/QuickSortRecursive.js | 60 ++++++++++++++++----------- Sorts/test/QuickSortRecursive.test.js | 16 ++----- 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/Sorts/QuickSortRecursive.js b/Sorts/QuickSortRecursive.js index 94aba3aff1..79d8139096 100644 --- a/Sorts/QuickSortRecursive.js +++ b/Sorts/QuickSortRecursive.js @@ -15,7 +15,6 @@ Problem & Source of Explanation => https://www.cs.auckland.ac.nz/software/AlgAnim/qsort1a.html */ - /** * Sorts the input list using the quicksort algorithm. * @@ -27,10 +26,12 @@ const quickSort = (inputList) => { if (!Array.isArray(inputList)) { throw new TypeError('Please input a valid list or array.') } + if (inputList.length <= 1) { + return inputList + } return quickSortHelper(inputList, 0, inputList.length - 1) } - /** * Recursively sorts the input list using the quicksort algorithm. * @@ -41,13 +42,10 @@ const quickSort = (inputList) => { */ const quickSortHelper = (inputList, low, high) => { - // base case if (low < high) { - // get the partition index. - const pIndex = partition(inputList, low, high) - // recursively call the quickSort method again. - quickSortHelper(inputList, low, pIndex - 1) - quickSortHelper(inputList, pIndex + 1, high) + const pIndex = partition(inputList, low, high) // Partition the array + quickSortHelper(inputList, low, pIndex - 1) // Sort left subarray + quickSortHelper(inputList, pIndex + 1, high) // Sort right subarray } return inputList } @@ -60,28 +58,37 @@ const quickSortHelper = (inputList, low, high) => { * @returns {number} `pIndex` pivot index value. */ const partition = (partitionList, low, high) => { - let mid =Math.floor((low + high) / 2) - // get the median of three is good technique for partitioning to be sure that the 2 sub-arrays will be almost equal or near - const pivot = medianOfThree(partitionList, low, mid, high) + const mid = Math.floor((low + high) / 2) + // get the median of three is good technique for partitioning to be sure that the 2 sub-arrays will be almost equal or nearly equal in size + const pivot = medianOfThree(partitionList, low, mid, high) // Find the pivot element + + // Move pivot to the end + let pivotIndex = partitionList.indexOf(pivot) + ;[partitionList[pivotIndex], partitionList[high]] = [ + partitionList[high], + partitionList[pivotIndex] + ] + let pIndex = low - for (let index = low; index <= high - 1; index++) { - if (partitionList[index] < pivot) { - // swap variables using array destructuring - ;[partitionList[index], partitionList[pIndex]] = [ + + // Perform the partitioning + for (let i = low; i < high; i++) { + if (partitionList[i] < pivot) { + ;[partitionList[i], partitionList[pIndex]] = [ partitionList[pIndex], - partitionList[index] + partitionList[i] ] - pIndex += 1 + pIndex++ } } + // Swap the pivot element back to its correct position ;[partitionList[pIndex], partitionList[high]] = [ partitionList[high], partitionList[pIndex] ] - return pIndex -} - + return pIndex // Return the partition index +} /** * Returns the median value of three elements in an array. * @@ -92,11 +99,14 @@ const partition = (partitionList, low, high) => { * @return {number} the median value of the three elements */ -const medianOfThree = (partitionList, low,mid, high) => { - const a = partitionList[low], b = partitionList[mid], c = partitionList[high]; - if ((a > b) !== (a > c)) return a; - else if ((b > a) !== (b > c)) return b; - else return c; +const medianOfThree = (partitionList, low, mid, high) => { + const a = partitionList[low] + const b = partitionList[mid] + const c = partitionList[high] + + if (a > b !== a > c) return a + else if (b > a !== b > c) return b + else return c } export { quickSort } diff --git a/Sorts/test/QuickSortRecursive.test.js b/Sorts/test/QuickSortRecursive.test.js index 5e258dce03..978a5d298e 100644 --- a/Sorts/test/QuickSortRecursive.test.js +++ b/Sorts/test/QuickSortRecursive.test.js @@ -5,27 +5,19 @@ describe('QuickSortRecursive | Partition In Place Method', () => { expect(() => quickSort('xyz')).toThrow( 'Please input a valid list or array.' ) - expect(() => quickSort(null)).toThrow( - 'Please input a valid list or array.' - ) - expect(() => quickSort(55)).toThrow( - 'Please input a valid list or array.' - ) + expect(() => quickSort(null)).toThrow('Please input a valid list or array.') + expect(() => quickSort(55)).toThrow('Please input a valid list or array.') }) it('Expectedly, the quickSort method will sort the unsorted list in ascending order', () => { const unSortArray = [5, 9, 3, 4, 6, 2, 0, 1, 7, 8] const sortedExpectedArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - expect(quickSort(unSortArray)).toEqual( - sortedExpectedArray - ) + expect(quickSort(unSortArray)).toEqual(sortedExpectedArray) }) it('Expectedly, the quickSort method will arrange the list of character values in dictionary order.', () => { const unSortList = ['d', 'e', 'c', 'a', 'f', 'b'] const sortedExpectedList = ['a', 'b', 'c', 'd', 'e', 'f'] - expect(quickSort(unSortList)).toEqual( - sortedExpectedList - ) + expect(quickSort(unSortList)).toEqual(sortedExpectedList) }) })