Skip to content
This repository has been archived by the owner on Dec 4, 2023. It is now read-only.

Commit

Permalink
feat(algorithms): add counting sort for array of numbers (#77)
Browse files Browse the repository at this point in the history
* feat: add counting sort for array of numbers

* refactor(counting-sort.ts): change for loop syntax for readability
  • Loading branch information
jp-tran committed Jan 17, 2021
1 parent d08f572 commit f305d92
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
55 changes: 55 additions & 0 deletions src/algorithms/sort/counting-sort.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Sort an array of integers in-place and in ascending order using counting sort.
*
* Time complexity: O(n + k), where n is the number of elements in arr
* and k is the range of numbers in arr.
*
* Space complexity: O(n + k)
*
* @param arr - array of integers to sort
*/
const countingSort = (arr: number[]): void => {
if (arr.length == 0) {
return
}

// check that arr elements are integers
for (let idx = 0; idx < arr.length; idx++) {
if (!Number.isInteger(arr[idx])) {
console.error(`arr[${idx}] is not an integer`)
return
}
}

// implementation of counting sort below
const max = Math.max(...arr) // find largest integer in arr
const min = Math.min(...arr) // find smallest integer in arr
const range = max - min + 1 // calculate range of possible numbers
const counts: number[] = new Array(range).fill(0) // contains counts for each number in arr
const sortedArr: number[] = new Array(arr.length) // final sorted array

// get counts of each number in arr
for (const num of arr) {
counts[num - min]++
}

// modify counts array such that each element is the sum of previous counts
for (let i = 1; i < counts.length; i++) {
counts[i] += counts[i - 1]
}

// fill in sortedArr using the indices stored in the counts array
// traversing arr in reverse keeps the sort stable
for (let i = arr.length - 1; i >= 0; i--) {
const sortedIndex = counts[arr[i] - min] - 1
counts[arr[i] - min]--
sortedArr[sortedIndex] = arr[i]
}

// copy elements of sortedArr to input array
for (let i = 0; i < arr.length; i++) {
arr[i] = sortedArr[i]
}
}

export default countingSort
27 changes: 27 additions & 0 deletions test/algorithms/sort/counting-sort.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import countingSort from '../../../src/algorithms/sort/counting-sort'
import testCases from './test-cases'

describe('countingSort', () => {
console.error = jest.fn()

beforeEach(() => {
jest.clearAllMocks()
})

for (const [description, inputArray] of Object.entries(testCases)) {
if (description === 'array of floats') {
it(`raises error for ${description}`, () => {
countingSort(inputArray)
expect(console.error).toHaveBeenCalledTimes(1)
})
continue
}

it(`correctly sorts ${description}`, () => {
const soln = [...inputArray]
soln.sort((a, b) => a - b) // sort the copy in-place using native JS function
countingSort(inputArray)
expect(inputArray).toEqual(soln)
})
}
})

0 comments on commit f305d92

Please sign in to comment.