forked from trekhleb/javascript-algorithms
-
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.
- Loading branch information
Showing
8 changed files
with
134 additions
and
19 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import RadixSort from '../radix-sort/RadixSort'; | ||
|
||
/** | ||
* Bucket Sort | ||
* | ||
* @param {number[]} arr | ||
* @param {number} bucketsNum | ||
* @return {number[]} | ||
*/ | ||
export default function BucketSort(arr, bucketsNum = 1) { | ||
const buckets = new Array(bucketsNum).fill(null).map(() => []); | ||
|
||
const minValue = Math.min(...arr); | ||
const maxValue = Math.max(...arr); | ||
|
||
const bucketSize = Math.ceil(Math.max(1, (maxValue - minValue) / bucketsNum)); | ||
|
||
// Place elements into buckets. | ||
for (let i = 0; i < arr.length; i += 1) { | ||
const currValue = arr[i]; | ||
const bucketIndex = Math.floor((currValue - minValue) / bucketSize); | ||
|
||
// Edge case for max value. | ||
if (bucketIndex === bucketsNum) { | ||
buckets[bucketsNum - 1].push(currValue); | ||
} else { | ||
buckets[bucketIndex].push(currValue); | ||
} | ||
} | ||
|
||
// Sort individual buckets. | ||
for (let i = 0; i < buckets.length; i += 1) { | ||
// Let's use the Radix Sorter here. This may give us | ||
// the average O(n + k) time complexity to sort one bucket | ||
// (where k is a number of digits in the longest number). | ||
buckets[i] = new RadixSort().sort(buckets[i]); | ||
} | ||
|
||
// Merge sorted buckets into final output. | ||
const sortedArr = []; | ||
for (let i = 0; i < buckets.length; i += 1) { | ||
sortedArr.push(...buckets[i]); | ||
} | ||
|
||
return sortedArr; | ||
} |
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,35 @@ | ||
# Bucket Sort | ||
|
||
**Bucket sort**, or **bin sort**, is a sorting algorithm that works by distributing the elements of an array into a number of buckets. Each bucket is then sorted individually, either using a different sorting algorithm, or by recursively applying the bucket sorting algorithm. | ||
|
||
## Algorithm | ||
|
||
Bucket sort works as follows: | ||
|
||
1. Set up an array of initially empty `buckets`. | ||
2. **Scatter:** Go over the original array, putting each object in its `bucket`. | ||
3. Sort each non-empty `bucket`. | ||
4. **Gather:** Visit the `buckets` in order and put all elements back into the original array. | ||
|
||
Elements are distributed among bins: | ||
|
||
![Elements are distributed among bins](./images/bucket_sort_1.png) | ||
|
||
Then, elements are sorted within each bin: | ||
|
||
![Elements are sorted within each bin](./images/bucket_sort_2.png) | ||
|
||
|
||
## Complexity | ||
|
||
The computational complexity depends on the algorithm used to sort each bucket, the number of buckets to use, and whether the input is uniformly distributed. | ||
|
||
The **worst-case** time complexity of bucket sort is | ||
`O(n^2)` if the sorting algorithm used on the bucket is *insertion sort*, which is the most common use case since the expectation is that buckets will not have too many elements relative to the entire list. In the worst case, all elements are placed in one bucket, causing the running time to reduce to the worst-case complexity of insertion sort (all elements are in reverse order). If the worst-case running time of the intermediate sort used is `O(n * log(n))`, then the worst-case running time of bucket sort will also be | ||
`O(n * log(n))`. | ||
|
||
On **average**, when the distribution of elements across buckets is reasonably uniform, it can be shown that bucket sort runs on average `O(n + k)` for `k` buckets. | ||
|
||
## References | ||
|
||
- [Bucket Sort on Wikipedia](https://en.wikipedia.org/wiki/Bucket_sort) |
33 changes: 33 additions & 0 deletions
33
src/algorithms/sorting/bucket-sort/__test__/BucketSort.test.js
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,33 @@ | ||
import BucketSort from '../BucketSort'; | ||
import { | ||
equalArr, | ||
notSortedArr, | ||
reverseArr, | ||
sortedArr, | ||
} from '../../SortTester'; | ||
|
||
describe('BucketSort', () => { | ||
it('should sort the array of numbers with different buckets amounts', () => { | ||
expect(BucketSort(notSortedArr, 4)).toEqual(sortedArr); | ||
expect(BucketSort(equalArr, 4)).toEqual(equalArr); | ||
expect(BucketSort(reverseArr, 4)).toEqual(sortedArr); | ||
expect(BucketSort(sortedArr, 4)).toEqual(sortedArr); | ||
|
||
expect(BucketSort(notSortedArr, 10)).toEqual(sortedArr); | ||
expect(BucketSort(equalArr, 10)).toEqual(equalArr); | ||
expect(BucketSort(reverseArr, 10)).toEqual(sortedArr); | ||
expect(BucketSort(sortedArr, 10)).toEqual(sortedArr); | ||
|
||
expect(BucketSort(notSortedArr, 50)).toEqual(sortedArr); | ||
expect(BucketSort(equalArr, 50)).toEqual(equalArr); | ||
expect(BucketSort(reverseArr, 50)).toEqual(sortedArr); | ||
expect(BucketSort(sortedArr, 50)).toEqual(sortedArr); | ||
}); | ||
|
||
it('should sort the array of numbers with the default buckets of 1', () => { | ||
expect(BucketSort(notSortedArr)).toEqual(sortedArr); | ||
expect(BucketSort(equalArr)).toEqual(equalArr); | ||
expect(BucketSort(reverseArr)).toEqual(sortedArr); | ||
expect(BucketSort(sortedArr)).toEqual(sortedArr); | ||
}); | ||
}); |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.