From 1ad60dc5107216e1f6febf7255e5fc915588c94b Mon Sep 17 00:00:00 2001 From: Oleksii Trekhleb Date: Mon, 13 Mar 2023 14:12:43 +0100 Subject: [PATCH] Add Bucket Sort. --- README.md | 1 + .../sorting/bucket-sort/BucketSort.js | 46 ++++++++++++++++++ src/algorithms/sorting/bucket-sort/README.md | 35 +++++++++++++ .../bucket-sort/__test__/BucketSort.test.js | 33 +++++++++++++ .../bucket-sort/images/bucket_sort_1.png | Bin 0 -> 11151 bytes .../bucket-sort/images/bucket_sort_2.png | Bin 0 -> 12936 bytes src/algorithms/sorting/radix-sort/README.md | 38 +++++++-------- .../sorting/radix-sort/images/radix-sort.png | Bin 0 -> 12619 bytes 8 files changed, 134 insertions(+), 19 deletions(-) create mode 100644 src/algorithms/sorting/bucket-sort/BucketSort.js create mode 100644 src/algorithms/sorting/bucket-sort/README.md create mode 100644 src/algorithms/sorting/bucket-sort/__test__/BucketSort.test.js create mode 100644 src/algorithms/sorting/bucket-sort/images/bucket_sort_1.png create mode 100644 src/algorithms/sorting/bucket-sort/images/bucket_sort_2.png create mode 100644 src/algorithms/sorting/radix-sort/images/radix-sort.png diff --git a/README.md b/README.md index f7f4827c..443ee953 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,7 @@ a set of rules that precisely define a sequence of operations. * `B` [Shellsort](src/algorithms/sorting/shell-sort) * `B` [Counting Sort](src/algorithms/sorting/counting-sort) * `B` [Radix Sort](src/algorithms/sorting/radix-sort) + * `B` [Bucket Sort](src/algorithms/sorting/bucket-sort) * **Linked Lists** * `B` [Straight Traversal](src/algorithms/linked-list/traversal) * `B` [Reverse Traversal](src/algorithms/linked-list/reverse-traversal) diff --git a/src/algorithms/sorting/bucket-sort/BucketSort.js b/src/algorithms/sorting/bucket-sort/BucketSort.js new file mode 100644 index 00000000..a41e5892 --- /dev/null +++ b/src/algorithms/sorting/bucket-sort/BucketSort.js @@ -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; +} diff --git a/src/algorithms/sorting/bucket-sort/README.md b/src/algorithms/sorting/bucket-sort/README.md new file mode 100644 index 00000000..673ba80b --- /dev/null +++ b/src/algorithms/sorting/bucket-sort/README.md @@ -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) diff --git a/src/algorithms/sorting/bucket-sort/__test__/BucketSort.test.js b/src/algorithms/sorting/bucket-sort/__test__/BucketSort.test.js new file mode 100644 index 00000000..9cab525d --- /dev/null +++ b/src/algorithms/sorting/bucket-sort/__test__/BucketSort.test.js @@ -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); + }); +}); diff --git a/src/algorithms/sorting/bucket-sort/images/bucket_sort_1.png b/src/algorithms/sorting/bucket-sort/images/bucket_sort_1.png new file mode 100644 index 0000000000000000000000000000000000000000..da0de9172f5648c3f24955be60597ac871f3476a GIT binary patch literal 11151 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 H)1dzY1gKX& literal 0 HcmV?d00001 diff --git a/src/algorithms/sorting/bucket-sort/images/bucket_sort_2.png b/src/algorithms/sorting/bucket-sort/images/bucket_sort_2.png new file mode 100644 index 0000000000000000000000000000000000000000..7b6f32c75210c8746e0834a09bf20ec82482cd4d GIT binary patch literal 12936 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 I2pI(aFLR8DQvd(} literal 0 HcmV?d00001 diff --git a/src/algorithms/sorting/radix-sort/README.md b/src/algorithms/sorting/radix-sort/README.md index 80129278..108d7d19 100644 --- a/src/algorithms/sorting/radix-sort/README.md +++ b/src/algorithms/sorting/radix-sort/README.md @@ -3,37 +3,37 @@ _Read this in other languages:_ [_Português_](README.pt-BR.md), -In computer science, **radix sort** is a non-comparative integer sorting -algorithm that sorts data with integer keys by grouping keys by the individual +In computer science, **radix sort** is a non-comparative integer sorting +algorithm that sorts data with integer keys by grouping keys by the individual digits which share the same significant position and value. A positional notation -is required, but because integers can represent strings of characters -(e.g., names or dates) and specially formatted floating point numbers, radix +is required, but because integers can represent strings of characters +(e.g., names or dates) and specially formatted floating point numbers, radix sort is not limited to integers. *Where does the name come from?* In mathematical numeral systems, the *radix* or base is the number of unique digits, -including the digit zero, used to represent numbers in a positional numeral system. -For example, a binary system (using numbers 0 and 1) has a radix of 2 and a decimal +including the digit zero, used to represent numbers in a positional numeral system. +For example, a binary system (using numbers 0 and 1) has a radix of 2 and a decimal system (using numbers 0 to 9) has a radix of 10. ## Efficiency -The topic of the efficiency of radix sort compared to other sorting algorithms is -somewhat tricky and subject to quite a lot of misunderstandings. Whether radix -sort is equally efficient, less efficient or more efficient than the best -comparison-based algorithms depends on the details of the assumptions made. -Radix sort complexity is `O(wn)` for `n` keys which are integers of word size `w`. -Sometimes `w` is presented as a constant, which would make radix sort better -(for sufficiently large `n`) than the best comparison-based sorting algorithms, -which all perform `O(n log n)` comparisons to sort `n` keys. However, in -general `w` cannot be considered a constant: if all `n` keys are distinct, -then `w` has to be at least `log n` for a random-access machine to be able to -store them in memory, which gives at best a time complexity `O(n log n)`. That -would seem to make radix sort at most equally efficient as the best +The topic of the efficiency of radix sort compared to other sorting algorithms is +somewhat tricky and subject to quite a lot of misunderstandings. Whether radix +sort is equally efficient, less efficient or more efficient than the best +comparison-based algorithms depends on the details of the assumptions made. +Radix sort complexity is `O(wn)` for `n` keys which are integers of word size `w`. +Sometimes `w` is presented as a constant, which would make radix sort better +(for sufficiently large `n`) than the best comparison-based sorting algorithms, +which all perform `O(n log n)` comparisons to sort `n` keys. However, in +general `w` cannot be considered a constant: if all `n` keys are distinct, +then `w` has to be at least `log n` for a random-access machine to be able to +store them in memory, which gives at best a time complexity `O(n log n)`. That +would seem to make radix sort at most equally efficient as the best comparison-based sorts (and worse if keys are much longer than `log n`). -![Radix Sort](https://www.researchgate.net/publication/291086231/figure/fig1/AS:614214452404240@1523451545568/Simplistic-illustration-of-the-steps-performed-in-a-radix-sort-In-this-example-the.png) +![Radix Sort](./images/radix-sort.png) ## Complexity diff --git a/src/algorithms/sorting/radix-sort/images/radix-sort.png b/src/algorithms/sorting/radix-sort/images/radix-sort.png new file mode 100644 index 0000000000000000000000000000000000000000..0cf9bf9e4de3c8799b0d8949cb6ea059b3b489dc GIT binary patch literal 12619 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 literal 0 HcmV?d00001