1
1
# Bucket Sort
2
2
3
- [ Bucket Sort or Bin Sort] ( https://en.wikipedia.org/wiki/Bucket_sort ) is a distributed sorting algorithm, which sort elements from an array by performing these steps:
3
+ Bucket Sort, also known as Bin Sort, is a distributed sorting algorithm, which sort elements from an array by performing these steps:
4
4
5
5
1 ) Distribute the elements into buckets or bins.
6
6
2 ) Sort each bucket individually.
7
- 3 ) Merge the buckets in order to produce a sort array as results.
8
-
7
+ 3 ) Merge the buckets in order to produce a sorted array as the result.
9
8
10
9
See the algorithm in action [ here] ( https://www.cs.usfca.edu/~galles/visualization/BucketSort.html ) and [ here] ( http://www.algostructure.com/sorting/bucketsort.php ) .
11
10
12
-
13
11
The performance for execution time is:
14
12
15
13
| Case | Performance |
@@ -18,11 +16,11 @@ The performance for execution time is:
18
16
| Best | Omega(n + k) |
19
17
| Average | Theta(n + k) |
20
18
21
- Where ** n** = # elements and ** k** = #buckets
19
+ Where ** n** = the number of elements and ** k** is the number of buckets.
22
20
23
- On the ** best case** the algorithm distributes the elements uniformily between buckets, a few elements are placed on each bucket and sorting the buckets is * O(1)* . Rearranging the elements is one more run through the initial list.
24
- On the ** worst case** the elements are sent all to the same bucket, making the process takes * O(n^2)* .
21
+ In the * best case* , the algorithm distributes the elements uniformily between buckets, a few elements are placed on each bucket and sorting the buckets is ** O(1)** . Rearranging the elements is one more run through the initial list.
25
22
23
+ In the * worst case* , the elements are sent all to the same bucket, making the process take ** O(n^2)** .
26
24
27
25
## Pseudocode
28
26
@@ -39,22 +37,22 @@ A [pseudocode](https://en.wikipedia.org/wiki/Bucket_sort#Pseudocode) of the algo
39
37
40
38
## Graphically explained
41
39
42
- ### Distribute elements in buckets
40
+ 1 ) Distribute elements in buckets:
43
41
44
42
![ distribution step] ( https://upload.wikimedia.org/wikipedia/commons/6/61/Bucket_sort_1.png )
45
43
46
- ### Sorting inside every bucket and merging
44
+ 2 ) Sorting inside every bucket and merging:
47
45
48
46
![ sorting each bucket and merge] ( https://upload.wikimedia.org/wikipedia/commons/3/39/Bucket_sort_2.png )
49
47
50
- ##An example
48
+ ## An example
51
49
52
50
### Input
53
51
54
- Suppose we have the following list of elements: ` [2, 56, 4, 77, 26, 98, 55] ` .
55
- And we define 10 buckets will be used. To determine the capacity of each bucket we need to know the ` maximum element value ` , in this case ` 98 ` .
52
+ Suppose we have the following list of elements: ` [2, 56, 4, 77, 26, 98, 55] ` . Let's use 10 buckets. To determine the capacity of each bucket we need to know the * maximum element value* , in this case ` 98 ` .
56
53
57
54
So the buckets are:
55
+
58
56
* ` bucket 1 ` : from 0 to 9
59
57
* ` bucket 2 ` : from 10 to 19
60
58
* ` bucket 3 ` : from 20 to 29
@@ -64,10 +62,11 @@ So the buckets are:
64
62
65
63
Now we need to choose a distribution function.
66
64
67
- ` bucketNumber = ( elementValue / totalNumberOfBuckets) + 1 `
65
+ ` bucketNumber = (elementValue / totalNumberOfBuckets) + 1 `
68
66
69
- Such that applying that function we distribute all the elements in the buckets.
70
- In our example it is like following:
67
+ Such that by applying that function we distribute all the elements in the buckets.
68
+
69
+ In our example it is like the following:
71
70
72
71
1 . Apply the distribution function to ` 2 ` . ` bucketNumber = (2 / 10) + 1 = 1 `
73
72
2 . Apply the distribution function to ` 56 ` . ` bucketNumber = (56 / 10) + 1 = 6 `
@@ -99,155 +98,162 @@ Finally we go through all the buckets and put the elements back in the list:
99
98
` [2, 4, 26, 55, 56, 77, 98] `
100
99
101
100
101
+ ## Swift implementation
102
102
103
- ##Swift implementation
103
+ Here is a diagram that shows the functions, data structures and protocols for our bucker sort implementation:
104
104
105
- ###Classes
105
+ ![ classes ] ( Docs/BucketSort.png )
106
106
107
- ![ classes ] ( https://github.com/barbaramartina/swift-algorithm-club/blob/BucketSort/Bucket%20Sort/Docs/BucketSort.png )
107
+ #### Main function
108
108
109
- ###Code
109
+ ` bucketSort() ` is a generic function that can apply the algorithm to any element of type ` T ` , as long as ` T ` is ` Sortable ` .
110
110
111
- Bucket Sort implementation use the following functions, data structures and protocols:
111
+ ``` swift
112
+ public func bucketSort <T :Sortable >(elements : [T],
113
+ distributor : Distributor,
114
+ sorter : Sorter,
115
+ buckets : [Bucket<T>]) -> [T] {
116
+ precondition (allPositiveNumbers (elements))
117
+ precondition (enoughSpaceInBuckets (buckets, elements : elements))
112
118
113
- ####Main function
119
+ var bucketsCopy = buckets
120
+ for elem in elements {
121
+ distributor.distribute (elem, buckets : & bucketsCopy)
122
+ }
114
123
115
- ` bucketSort ` is a generic function that can apply the algorithm to any element of type T, as long as T is Sortable.
124
+ var results = [T]()
116
125
117
- public func bucketSort<T:Sortable>(elements: [T], distributor: Distributor,sorter: Sorter, buckets: [Bucket<T>]) -> [T] {
118
- precondition(allPositiveNumbers(elements))
119
- precondition(enoughSpaceInBuckets(buckets, elements: elements))
120
-
121
- var bucketsCopy = buckets
122
- for elem in elements {
123
- distributor.distribute(elem, buckets: &bucketsCopy)
124
- }
125
-
126
- var results = [T]()
127
-
128
- for bucket in bucketsCopy {
129
- results += bucket.sort(sorter)
130
- }
131
-
132
- return results
133
- }
126
+ for bucket in bucketsCopy {
127
+ results += bucket.sort (sorter)
128
+ }
134
129
130
+ return results
131
+ }
132
+ ```
135
133
136
- ####Bucket
134
+ #### Bucket
137
135
138
- public struct Bucket<T:Sortable> {
139
- var elements: [T]
140
- let capacity: Int
141
-
142
- public init(capacity: Int) {
143
- self.capacity = capacity
144
- elements = [T]()
145
- }
146
-
147
- public mutating func add(item: T) {
148
- if (elements.count < capacity) {
149
- elements.append(item)
150
- }
151
- }
152
-
153
- public func sort(algorithm: Sorter) -> [T] {
154
- return algorithm.sort(elements)
155
- }
156
- }
136
+ ``` swift
137
+ public struct Bucket <T :Sortable > {
138
+ var elements: [T]
139
+ let capacity: Int
157
140
158
- ####Sortable
141
+ public init (capacity : Int ) {
142
+ self .capacity = capacity
143
+ elements = [T]()
144
+ }
159
145
160
- public protocol Sortable: IntConvertible, Comparable {
161
- }
146
+ public mutating func add (item : T) {
147
+ if (elements.count < capacity) {
148
+ elements.append (item)
149
+ }
150
+ }
162
151
163
- ####IntConvertible
152
+ public func sort (algorithm : Sorter) -> [T] {
153
+ return algorithm.sort (elements)
154
+ }
155
+ }
156
+ ```
164
157
165
- The algorithm is designed to sort integers, so all the elements to be sorted should be mapped to an integer value.
158
+ #### Sortable
159
+
160
+ ``` swift
161
+ public protocol Sortable : IntConvertible , Comparable {
162
+ }
163
+ ```
166
164
167
- public protocol IntConvertible {
168
- func toInt() -> Int
169
- }
165
+ #### IntConvertible
166
+
167
+ The algorithm is designed to sort integers, so all the elements to be sorted should be mapped to an integer value.
170
168
169
+ ``` swift
170
+ public protocol IntConvertible {
171
+ func toInt () -> Int
172
+ }
173
+ ```
171
174
172
- ####Sorter
175
+ #### Sorter
173
176
174
- public protocol Sorter {
175
- func sort<T:Sortable>(items: [T]) -> [T]
176
- }
177
+ ``` swift
178
+ public protocol Sorter {
179
+ func sort <T :Sortable >(items : [T]) -> [T]
180
+ }
181
+ ```
177
182
178
- ####Distributor
183
+ #### Distributor
179
184
180
- public protocol Distributor {
181
- func distribute<T:Sortable>(element: T, inout buckets: [Bucket<T>])
182
- }
185
+ ``` swift
186
+ public protocol Distributor {
187
+ func distribute <T :Sortable >(element : T, inout buckets : [Bucket<T>])
188
+ }
189
+ ```
183
190
184
191
### Custom Sorter and Distributor
185
192
186
193
The current implementation make use of the following implementations for * Sorter* and * Distributor* .
187
194
188
195
* Sorter*
189
196
190
- public struct InsertionSorter: Sorter {
191
-
192
- public init() {}
193
-
194
- public func sort<T:Sortable>(items: [T]) -> [T] {
195
- var results = items
196
- for i in 0 ..< results.count {
197
- var j = i
198
- while ( j > 0 && results[j-1] > results[j]) {
199
-
200
- let auxiliar = results[j-1]
201
- results[j-1] = results[j]
202
- results[j] = auxiliar
203
-
204
- j -= 1
205
- }
206
- }
207
- return results
208
- }
209
- }
197
+ ``` swift
198
+ public struct InsertionSorter : Sorter {
199
+ public func sort <T :Sortable >(items : [T]) -> [T] {
200
+ var results = items
201
+ for i in 0 ..< results.count {
202
+ var j = i
203
+ while ( j > 0 && results[j- 1 ] > results[j]) {
204
+
205
+ let auxiliar = results[j- 1 ]
206
+ results[j- 1 ] = results[j]
207
+ results[j] = auxiliar
208
+
209
+ j -= 1
210
+ }
211
+ }
212
+ return results
213
+ }
214
+ }
215
+ ```
210
216
211
217
* Distributor*
212
218
213
- /*
214
- * An example of a simple distribution function that send every elements to
215
- * the bucket representing the range in which it fits.An
216
- *
217
- * If the range of values to sort is 0..<49 i.e, there could be 5 buckets of capacity = 10
218
- * So every element will be classified by the ranges:
219
- *
220
- * - 0 ..< 10
221
- * - 10 ..< 20
222
- * - 20 ..< 30
223
- * - 30 ..< 40
224
- * - 40 ..< 50
225
- *
226
- * By following the formula: element / capacity = #ofBucket
227
- */
228
- public struct RangeDistributor: Distributor {
229
-
230
- public init() {}
231
-
232
- public func distribute<T:Sortable>(element: T, inout buckets: [Bucket<T>]) {
233
- let value = element.toInt()
234
- let bucketCapacity = buckets.first!.capacity
235
-
236
- let bucketIndex = value / bucketCapacity
237
- buckets[bucketIndex].add(element)
238
- }
239
- }
219
+ ``` swift
220
+ /*
221
+ * An example of a simple distribution function that send every elements to
222
+ * the bucket representing the range in which it fits.
223
+ *
224
+ * If the range of values to sort is 0..<49 i.e, there could be 5 buckets of capacity = 10
225
+ * So every element will be classified by the ranges:
226
+ *
227
+ * - 0 ..< 10
228
+ * - 10 ..< 20
229
+ * - 20 ..< 30
230
+ * - 30 ..< 40
231
+ * - 40 ..< 50
232
+ *
233
+ * By following the formula: element / capacity = #ofBucket
234
+ */
235
+ public struct RangeDistributor : Distributor {
236
+ public func distribute <T :Sortable >(element : T, inout buckets : [Bucket<T>]) {
237
+ let value = element.toInt ()
238
+ let bucketCapacity = buckets.first ! .capacity
239
+
240
+ let bucketIndex = value / bucketCapacity
241
+ buckets[bucketIndex].add (element)
242
+ }
243
+ }
244
+ ```
240
245
241
246
### Make your own version
242
247
243
248
By reusing this code and implementing your own * Sorter* and * Distributor* you can experiment with different versions.
244
249
245
250
## Other variations of Bucket Sort
246
251
247
- The following are some of the variation to the General Bucket Sort implemented here:
252
+ The following are some of the variation to the general [ Bucket Sort] ( https://en.wikipedia.org/wiki/Bucket_sort ) implemented here:
248
253
249
254
- [ Proxmap Sort] ( https://en.wikipedia.org/wiki/Bucket_sort#ProxmapSort )
250
255
- [ Histogram Sort] ( https://en.wikipedia.org/wiki/Bucket_sort#Histogram_sort )
251
256
- [ Postman Sort] ( https://en.wikipedia.org/wiki/Bucket_sort#Postman.27s_sort )
252
257
- [ Shuffle Sort] ( https://en.wikipedia.org/wiki/Bucket_sort#Shuffle_sort )
253
258
259
+ * Written for Swift Algorithm Club by Barbara Rodeker. Images from Wikipedia.*
0 commit comments