Skip to content

Commit 7347dc2

Browse files
authored
Merge pull request #175 from Asterioxer/main
Pull Request: Implement Radix Sort in TypeScript (#141)
2 parents 046381c + e3ce2ec commit 7347dc2

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
/**
2+
* Get maximum value in array. Used to determine the number of digits for Radix Sort.
3+
* This function expects an array of positive numbers, as it's used internally
4+
* by radixSort on positive numbers or absolute values of negative numbers.
5+
*
6+
* @param arr - Array to find maximum in. Must not be empty and should contain positive numbers.
7+
* @returns Maximum value in the array.
8+
* @throws Error if the array is empty.
9+
*/
10+
function getMax(arr: number[]): number {
11+
if (arr.length === 0) {
12+
throw new Error("Array cannot be empty when getting max value");
13+
}
14+
let max = arr[0]; // Assume arr[0] is positive as per function contract
15+
for (let i = 1; i < arr.length; i++) {
16+
if (arr[i] > max) {
17+
max = arr[i];
18+
}
19+
}
20+
return max;
21+
}
22+
23+
/** * Count Sort Algorithm Implementation in TypeScript.
24+
* @param arr - Array of numbers to be sorted (or a part of it, e.g., positive numbers or absolute values of negative numbers).
25+
* The function modifies this array in place.
26+
* @param exp - The current digit's place value (e.g., 1 for units digit, 10 for tens digit, base for base's place).
27+
* @param base - The numeral system base (e.g., 10 for decimal, 2 for binary).
28+
*/
29+
function countSort(arr: number[], exp: number, base: number): void {
30+
const output = new Array(arr.length);
31+
const count = new Array(base).fill(0);
32+
33+
for (let i = 0; i < arr.length; i++) {
34+
count[Math.floor(Math.abs(arr[i]) / exp) % base]++;
35+
}
36+
37+
for (let i = 1; i < base; i++) {
38+
count[i] += count[i - 1];
39+
}
40+
41+
for (let i = arr.length - 1; i >= 0; i--) {
42+
const index = Math.floor(Math.abs(arr[i]) / exp) % base;
43+
output[count[index] - 1] = arr[i];
44+
count[index]--;
45+
}
46+
47+
for (let i = 0; i < arr.length; i++) {
48+
arr[i] = output[i];
49+
}
50+
}
51+
52+
/**
53+
* Radix Sort Algorithm Implementation in TypeScript.
54+
*
55+
* Sorts an array of numbers (positive and negative) using the Radix Sort algorithm.
56+
* The sort is stable.
57+
*
58+
* @remarks
59+
* Radix sort is a non-comparative sorting algorithm. It avoids comparison by creating
60+
* and distributing elements into buckets according to their radix. For elements with
61+
* more than one significant digit, this bucketing process is repeated for each digit,
62+
* while preserving the ordering of the prior step, until all digits have been considered.
63+
*
64+
* **Time Complexity:** O(d * (n + b))
65+
* Where:
66+
* - n is the number of elements in the array.
67+
* - d is the maximum number of digits in any number in the array (for the given base).
68+
*
69+
* - b is the base used for sorting.
70+
* In cases where d -> constant and b ! significantly larger than n, Radix Sort can perform linearly, O(n).
71+
*
72+
* **Space Complexity:** O(n + b)
73+
* This is due to:
74+
* - The output array of size n and count array of size b used in each call to countSort.
75+
* - Additional arrays for separating negative and positive numbers, each potentially up to size n.
76+
*
77+
* @param arr - The array of numbers to be sorted.
78+
* @param base - The base of the numeral system to be used for sorting (e.g., 10 for decimal, 2 for binary).
79+
* Must be an integer greater than or equal to 2. Defaults to 10.
80+
* @returns A new array containing the sorted numbers.
81+
* @throws Error if the base is less than 2.
82+
*/
83+
function radixSort(arr: number[], base: number = 10): number[] {
84+
if (arr.length <= 1) {
85+
return [...arr];
86+
}
87+
88+
if (base < 2) {
89+
throw new Error("Base must be at least 2");
90+
}
91+
92+
const negativeNumbers = arr.filter(num => num < 0);
93+
const positiveNumbers = arr.filter(num => num >= 0);
94+
95+
let sortedNegativeNumbers: number[] = [];
96+
if (negativeNumbers.length > 0) {
97+
98+
const absNegativeNumbers = negativeNumbers.map(num => Math.abs(num));
99+
100+
if (absNegativeNumbers.length > 0) {
101+
const maxNeg = getMax(absNegativeNumbers);
102+
for (let exp = 1; Math.floor(maxNeg / exp) > 0; exp *= base) {
103+
countSort(absNegativeNumbers, exp, base);
104+
}
105+
}
106+
sortedNegativeNumbers = absNegativeNumbers.map(num => -num).reverse();
107+
}
108+
109+
let sortedPositiveNumbers: number[] = [];
110+
if (positiveNumbers.length > 0) {
111+
const maxPos = getMax(positiveNumbers);
112+
for (let exp = 1; Math.floor(maxPos / exp) > 0; exp *= base) {
113+
countSort(positiveNumbers, exp, base);
114+
}
115+
sortedPositiveNumbers = positiveNumbers;
116+
}
117+
118+
return [...sortedNegativeNumbers, ...sortedPositiveNumbers];
119+
}
120+
121+
122+
123+
export { getMax, countSort, radixSort };

0 commit comments

Comments
 (0)