-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #19 from iamwill123/add/quick-sort
add quick sort
- Loading branch information
Showing
7 changed files
with
294 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/* | ||
quick sort is a divide and conquer algorithm that recursively divides a list into a smaller list and a larger list based on a pivot element. It then sorts the smaller list and the larger list by recursively calling itself. This process continues until the entire list is sorted. Here we are using the Lomuto partition scheme. | ||
*/ | ||
|
||
import { | ||
compare, | ||
endTime, | ||
howLongExecTook, | ||
isAnObj, | ||
pickRandomIndex, | ||
startTime, | ||
} from '../../helpers' | ||
import { ArrayInput, SortInput, SortOutput } from '../../../types/sorts' | ||
|
||
type HelperInput = { | ||
arr: ArrayInput | ||
startIdx: number | ||
endIdx: number | ||
partitionType: string | ||
order: string | ||
key: string | ||
callback: Function | ||
animate: boolean | ||
} | ||
|
||
async function quick_sort( | ||
input: SortInput, | ||
partitionType: string = 'lomuto' | ||
): Promise<SortOutput> { | ||
const _s = startTime() | ||
const { | ||
arr, | ||
order = 'asc', | ||
key = '', | ||
callback = () => {}, | ||
isSorting = () => true, | ||
} = input | ||
|
||
const n: number = arr.length | ||
let startIdx: number = 0 | ||
let endIdx: number = n - 1 | ||
|
||
let animate: boolean = false | ||
|
||
if (n <= 0 || !isSorting()) { | ||
return { arr, key, order, n, execTime: 0, animate: false } | ||
} | ||
|
||
if (isAnObj(0, arr) && !key) throw new Error('key is required') | ||
|
||
// recursive case | ||
helper({ | ||
arr, | ||
startIdx, | ||
endIdx, | ||
partitionType, | ||
order, | ||
key, | ||
callback, | ||
animate, | ||
}) | ||
|
||
const _e = endTime() | ||
const execTimeInMs = howLongExecTook(_s, _e) | ||
|
||
return { | ||
arr, | ||
key, | ||
order, | ||
n, | ||
execTime: execTimeInMs, | ||
animate, | ||
} | ||
} | ||
|
||
function helper(helperInput: HelperInput) { | ||
const { | ||
arr, | ||
startIdx, | ||
endIdx, | ||
partitionType, | ||
order, | ||
key, | ||
callback, | ||
animate, | ||
} = helperInput | ||
|
||
// base case | ||
// the leaf workers either 1 or 0 | ||
if (startIdx >= endIdx) return | ||
|
||
let pivotIdx = pickRandomIndex(startIdx, endIdx) | ||
let pivotElem = arr[pivotIdx] | ||
// make the pivot value the start of the array | ||
;[arr[startIdx], arr[pivotIdx]] = [arr[pivotIdx], arr[startIdx]] | ||
|
||
let smaller = 0, | ||
bigger = 0 | ||
|
||
if (partitionType === 'hoare') { | ||
// hoare's partitioning | ||
smaller = startIdx + 1 | ||
bigger = endIdx | ||
|
||
while (smaller <= bigger) { | ||
// compare the next number at "smaller" to the pivot elem at startIdx | ||
if (compare(arr[smaller], pivotElem, key, order) <= 0) { | ||
smaller++ | ||
} else if (compare(arr[bigger], pivotElem, key, order) > 0) { | ||
bigger-- | ||
} else { | ||
;[arr[smaller], arr[bigger]] = [arr[bigger], arr[smaller]] | ||
smaller++ | ||
bigger-- | ||
} | ||
} | ||
|
||
// put the pivot element to where the smaller index left off after the loop | ||
;[arr[startIdx], arr[bigger]] = [arr[bigger], arr[startIdx]] | ||
|
||
// recursive case | ||
helper({ ...helperInput, endIdx: bigger }) // include the pivot in the first half | ||
helper({ ...helperInput, startIdx: bigger + 1 }) // start from the next element of the pivot | ||
} | ||
|
||
if (partitionType === 'lomuto') { | ||
// lomuto's partitioning | ||
smaller = startIdx | ||
bigger = startIdx | ||
for (let i = bigger + 1; i <= endIdx; i++) { | ||
// compare the next number at "bigger" to the pivot elem at startIdx | ||
if (compare(arr[i], pivotElem, key, order) < 0) { | ||
smaller++ | ||
;[arr[smaller], arr[i]] = [arr[i], arr[smaller]] | ||
} | ||
} | ||
// put the pivot element to where the smaller index left off after the loop | ||
;[arr[startIdx], arr[smaller]] = [arr[smaller], arr[startIdx]] | ||
|
||
// recursive case | ||
helper({ ...helperInput, endIdx: smaller - 1 }) | ||
helper({ ...helperInput, startIdx: smaller + 1 }) | ||
} | ||
} | ||
|
||
export default quick_sort |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import quick from '../../../src/lib/sorts/quick' | ||
import { cases } from '../test-cases' | ||
import { testData } from '../test-data' | ||
|
||
describe('quick sort', () => { | ||
const { unsorted, sorted } = testData | ||
test('cases[0]: ' + cases[0], async () => { | ||
const obj = { arr: [5] } | ||
const { arr: arrOfNums } = await quick(obj) | ||
expect(arrOfNums).toEqual([5]) | ||
|
||
const obj1 = { arr: [] } | ||
const { arr: arrOfNums1 } = await quick(obj1) | ||
expect(arrOfNums1).toEqual([]) | ||
}) | ||
|
||
test('cases[1]: ' + cases[1], async () => { | ||
const obj = { arr: unsorted().arr.numbers } | ||
const { arr: arrOfNums } = await quick(obj) | ||
expect(arrOfNums).toEqual(sorted().arr.numbers) | ||
}) | ||
|
||
test('cases[2]: ' + cases[2], async () => { | ||
let order = 'desc' | ||
const obj = { arr: unsorted().arr.numbers, order } | ||
const { arr: arrOfNums } = await quick(obj) | ||
expect(arrOfNums).toEqual(sorted({ order }).arr.numbers) | ||
}) | ||
|
||
test('cases[3]: ' + cases[3], async () => { | ||
const obj = { | ||
arr: unsorted().arr.objects, | ||
key: 'age', | ||
} | ||
const { arr: arrOfObjs } = await quick(obj) | ||
|
||
expect(arrOfObjs).toEqual(sorted({}).arr.objects) | ||
}) | ||
|
||
test('cases[4]: ' + cases[4], async () => { | ||
let key = 'height', | ||
order = 'desc' | ||
const obj = { | ||
arr: unsorted({ key }).arr.objects, | ||
key, | ||
order, | ||
} | ||
const { arr: arrOfObjs } = await quick(obj) | ||
expect(arrOfObjs).toEqual(sorted({ key, order }).arr.objects) | ||
}) | ||
|
||
test('cases[5]: ' + cases[5], async () => { | ||
const obj = { | ||
arr: unsorted().arr.numbers, | ||
isSorting: () => false, | ||
} | ||
const { arr: arrOfNums } = await quick(obj) | ||
expect(arrOfNums).toEqual(unsorted().arr.numbers) | ||
}) | ||
|
||
test.todo('cases[6]: ' + cases[6]) | ||
// test('cases[6]: ' + cases[6], async () => { | ||
// const obj = { | ||
// arr: unsorted().arr.numbers, | ||
// callback: async (a: number, b: number) => { | ||
// return await Promise.resolve() | ||
// }, | ||
// } | ||
// const { arr: arrOfNums, animate } = await quick(obj) | ||
// expect(arrOfNums).toEqual(sorted().arr.numbers) | ||
// expect(animate).toEqual(true) | ||
// }) | ||
|
||
test.todo('cases[7]: ' + cases[7]) | ||
// test('cases[7]: ' + cases[7], async () => { | ||
// const obj = { | ||
// arr: unsorted().arr.numbers, | ||
// callback: async () => { | ||
// return await Promise.resolve() | ||
// }, | ||
// } | ||
// const { arr: arrOfNums, animate } = await quick(obj) | ||
// expect(arrOfNums).toEqual(sorted().arr.numbers) | ||
// expect(animate).toEqual(false) | ||
// }) | ||
test('cases[8]: should sort correctly when switching partition type to "hoare"', async () => { | ||
const partitionType = 'hoare' | ||
const obj = { | ||
arr: unsorted().arr.numbers, | ||
} | ||
const { arr: arrOfNums } = await quick(obj, partitionType) | ||
expect(arrOfNums).toEqual(sorted().arr.numbers) | ||
|
||
let key = 'height', | ||
order = 'desc' | ||
const obj1 = { | ||
arr: unsorted({ key }).arr.objects, | ||
key, | ||
order, | ||
} | ||
const { arr: arrOfObjs } = await quick(obj1, partitionType) | ||
expect(arrOfObjs).toEqual(sorted({ key, order }).arr.objects) | ||
}) | ||
}) |
3fde8ce
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
collection-of-algos – ./
collection-of-algos-iamwill1.vercel.app
collection-of-algos-git-main-iamwill1.vercel.app
collection-of-algos.vercel.app