Skip to content

Fixes: #1703 Improve QuickSort Algorithm with Better Space Complexity #1707

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
* [ROT13](Ciphers/ROT13.js)
* [VigenereCipher](Ciphers/VigenereCipher.js)
* [XORCipher](Ciphers/XORCipher.js)
* **Compression**
* [RLE](Compression/RLE.js)
* **Conversions**
* [ArbitraryBase](Conversions/ArbitraryBase.js)
* [ArrayBufferToBase64](Conversions/ArrayBufferToBase64.js)
Expand Down Expand Up @@ -285,6 +287,7 @@
* [Problem016](Project-Euler/Problem016.js)
* [Problem017](Project-Euler/Problem017.js)
* [Problem018](Project-Euler/Problem018.js)
* [Problem019](Project-Euler/Problem019.js)
* [Problem020](Project-Euler/Problem020.js)
* [Problem021](Project-Euler/Problem021.js)
* [Problem023](Project-Euler/Problem023.js)
Expand Down
48 changes: 32 additions & 16 deletions Sorts/QuickSort.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,46 @@
/**
* @function QuickSort
* @function quickSort
* @description Quick sort is a comparison sorting algorithm that uses a divide and conquer strategy.
* @param {Integer[]} items - Array of integers
* This version optimizes space complexity by sorting the array in place.
* @param {Integer[]} items - Array of integers to be sorted.
* @param {number} left - The starting index (defaults to 0).
* @param {number} right - The ending index (defaults to array length - 1).
* @return {Integer[]} - Sorted array.
* @see [QuickSort](https://en.wikipedia.org/wiki/Quicksort)
*/
function quickSort(items) {
const length = items.length
function quickSort(items, left = 0, right = items.length - 1) {
if (left < right) {
let pivotIndex = partition(items, left, right)

if (length <= 1) {
return items
quickSort(items, left, pivotIndex - 1)
quickSort(items, pivotIndex + 1, right)
}
const PIVOT = items[0]
const GREATER = []
const LESSER = []
return items
}

/**
* @function partition
* @description This function partitions the array using the last element as the pivot.
* It ensures that all elements smaller than the pivot are on the left side,
* and all greater elements are on the right side.
* @param {Integer[]} items - Array of integers to partition.
* @param {number} left - The starting index for partitioning.
* @param {number} right - The ending index for partitioning.
* @return {number} - The index of the pivot element after partitioning.
*/
function partition(items, left, right) {
const pivot = items[right]
let i = left - 1

for (let i = 1; i < length; i++) {
if (items[i] > PIVOT) {
GREATER.push(items[i])
} else {
LESSER.push(items[i])
for (let j = left; j < right; j++) {
if (items[j] <= pivot) {
i++
;[items[i], items[j]] = [items[j], items[i]]
}
}

const sorted = [...quickSort(LESSER), PIVOT, ...quickSort(GREATER)]
return sorted
;[items[i + 1], items[right]] = [items[right], items[i + 1]]
return i + 1
}

export { quickSort }
90 changes: 38 additions & 52 deletions Sorts/QuickSortRecursive.js
Original file line number Diff line number Diff line change
@@ -1,65 +1,51 @@
/*
Quicksort is the most popular sorting algorithm and there have
lots of different implementations but the "recursive" or "Partition in place"
is one of the most efficient implementations below we have discussed how to
implement it.

Partition in place => "in place" Partition in place indicates that we
do not need any other space to store the auxiliary array and the term
"partition" denotes that we split the list into two parts one is less
than the pivot and the other is greater than the pivot and repeats this
process recursively and breaks the problem into sub-problems and makes
it singular so that the behavior or "divide and conquer" get involved
too.

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.
* @function quickSort
* @description Quick sort is a comparison sorting algorithm that uses a divide and conquer strategy.
* This version optimizes space complexity by sorting the array in place.
* @param {Integer[]} items - Array of integers to be sorted.
* @param {number} left - The starting index (defaults to 0).
* @param {number} right - The ending index (defaults to array length - 1).
* @return {Integer[]} - Sorted array.
* @throws Will throw an error if the input is not an array.
* @see [QuickSort](https://en.wikipedia.org/wiki/Quicksort)
*/
const quickSort = (inputList, low, high) => {
if (!Array.isArray(inputList)) {
throw new TypeError('Please input a valid list or array.')
function quickSort(items, left = 0, right = items.length - 1) {
if (!Array.isArray(items)) {
throw new Error('Please input a valid list or array.')
}
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)

if (left < right) {
let pivotIndex = partition(items, left, right)
quickSort(items, left, pivotIndex - 1)
quickSort(items, pivotIndex + 1, right)
}
return inputList

return items
}

/**
* Partition In Place method.
* @param {number[]} partitionList list for partitioning.
* @param {number} low lower index for partition.
* @param {number} high higher index for partition.
* @returns {number} `pIndex` pivot index value.
* @function partition
* @description This function partitions the array using the last element as the pivot.
* It ensures that all elements smaller than the pivot are on the left side,
* and all greater elements are on the right side.
* @param {Integer[]} items - Array of integers to partition.
* @param {number} left - The starting index for partitioning.
* @param {number} right - The ending index for partitioning.
* @return {number} - The index of the pivot element after partitioning.
*/
const partition = (partitionList, low, high) => {
const pivot = partitionList[high]
let pIndex = low
for (let index = low; index <= high - 1; index++) {
if (partitionList[index] < pivot) {
// swap variables using array destructuring
;[partitionList[index], partitionList[pIndex]] = [
partitionList[pIndex],
partitionList[index]
]
pIndex += 1
function partition(items, left, right) {
const pivot = items[right]
let i = left - 1

for (let j = left; j < right; j++) {
if (items[j] <= pivot) {
i++
;[items[i], items[j]] = [items[j], items[i]]
}
}
;[partitionList[pIndex], partitionList[high]] = [
partitionList[high],
partitionList[pIndex]
]
return pIndex

;[items[i + 1], items[right]] = [items[right], items[i + 1]]
return i + 1
}

export { quickSort }
10 changes: 6 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
"author": "TheAlgorithms",
"license": "GPL-3.0",
"devDependencies": {
"@vitest/coverage-v8": "^1.2.1",
"globby": "^13.2.2",
"husky": "^8.0.3",
"husky": "^9.1.6",
"prettier": "^3.0.3",
"vitest": "^1.2.1",
"@vitest/coverage-v8": "^1.2.1"
"vitest": "^1.2.1"
},
"engines": {
"node": ">=20.6.0"
Expand Down