|
1 | 1 | from pydatastructs.linear_data_structures.arrays import (
|
2 |
| - OneDimensionalArray, DynamicArray) |
| 2 | + OneDimensionalArray, DynamicArray, Array) |
3 | 3 | from pydatastructs.utils.misc_util import _check_type, _comp
|
4 | 4 | from concurrent.futures import ThreadPoolExecutor
|
5 | 5 | from math import log, floor
|
|
9 | 9 | 'brick_sort',
|
10 | 10 | 'brick_sort_parallel',
|
11 | 11 | 'heapsort',
|
12 |
| - 'matrix_multiply_parallel' |
| 12 | + 'matrix_multiply_parallel', |
| 13 | + 'counting_sort' |
13 | 14 | ]
|
14 | 15 |
|
15 | 16 | def _merge(array, sl, el, sr, er, end, comp):
|
@@ -294,6 +295,83 @@ def heapsort(array, **kwargs):
|
294 | 295 | if _check_type(array, DynamicArray):
|
295 | 296 | array._modify(force=True)
|
296 | 297 |
|
| 298 | +def counting_sort(array: Array) -> Array: |
| 299 | + """ |
| 300 | + Performs counting sort on the given array. |
| 301 | +
|
| 302 | + Parameters |
| 303 | + ========== |
| 304 | +
|
| 305 | + array: Array |
| 306 | + The array which is to be sorted. |
| 307 | +
|
| 308 | + Returns |
| 309 | + ======= |
| 310 | +
|
| 311 | + output: Array |
| 312 | + The sorted array. |
| 313 | +
|
| 314 | + Examples |
| 315 | + ======== |
| 316 | +
|
| 317 | + >>> from pydatastructs import DynamicOneDimensionalArray as DODA, counting_sort |
| 318 | + >>> arr = DODA(int, [5, 78, 1, 0]) |
| 319 | + >>> out = counting_sort(arr) |
| 320 | + >>> str(out) |
| 321 | + "['0', '1', '5', '78']" |
| 322 | + >>> arr.delete(2) |
| 323 | + >>> out = counting_sort(arr) |
| 324 | + >>> str(out) |
| 325 | + "['0', '5', '78']" |
| 326 | +
|
| 327 | + References |
| 328 | + ========== |
| 329 | +
|
| 330 | + .. [1] https://en.wikipedia.org/wiki/Counting_sort |
| 331 | +
|
| 332 | + Note |
| 333 | + ==== |
| 334 | +
|
| 335 | + Since, counting sort is a non-comparison sorting algorithm, |
| 336 | + custom comparators aren't allowed. |
| 337 | + The ouput array doesn't contain any `None` value. |
| 338 | + """ |
| 339 | + max_val, min_val = array[0], array[0] |
| 340 | + none_count = 0 |
| 341 | + for i in range(len(array)): |
| 342 | + if array[i] is not None: |
| 343 | + if max_val is None or max_val < array[i]: |
| 344 | + max_val = array[i] |
| 345 | + if min_val is None or array[i] < min_val: |
| 346 | + min_val = array[i] |
| 347 | + else: |
| 348 | + none_count += 1 |
| 349 | + if min_val is None or max_val is None: |
| 350 | + return array |
| 351 | + |
| 352 | + count = [0 for _ in range(max_val - min_val + 1)] |
| 353 | + for i in range(len(array)): |
| 354 | + if array[i] is not None: |
| 355 | + count[array[i] - min_val] += 1 |
| 356 | + |
| 357 | + total = 0 |
| 358 | + for i in range(max_val - min_val + 1): |
| 359 | + count[i], total = total, count[i] + total |
| 360 | + |
| 361 | + output = type(array)(array._dtype, |
| 362 | + [array[i] for i in range(len(array)) |
| 363 | + if array[i] is not None]) |
| 364 | + if _check_type(output, DynamicArray): |
| 365 | + output._modify(force=True) |
| 366 | + |
| 367 | + for i in range(len(array)): |
| 368 | + x = array[i] |
| 369 | + if x is not None: |
| 370 | + output[count[x-min_val]] = x |
| 371 | + count[x-min_val] += 1 |
| 372 | + |
| 373 | + return output |
| 374 | + |
297 | 375 | def _matrix_multiply_helper(m1, m2, row, col):
|
298 | 376 | s = 0
|
299 | 377 | for i in range(len(m1)):
|
|
0 commit comments