diff --git a/docs/source/pydatastructs/linear_data_structures/algorithms.rst b/docs/source/pydatastructs/linear_data_structures/algorithms.rst index 7ab521cfd..1a5cbf399 100644 --- a/docs/source/pydatastructs/linear_data_structures/algorithms.rst +++ b/docs/source/pydatastructs/linear_data_structures/algorithms.rst @@ -45,4 +45,6 @@ Algorithms .. autofunction:: pydatastructs.jump_search -.. autofunction:: pydatastructs.intro_sort \ No newline at end of file +.. autofunction:: pydatastructs.intro_sort + +.. autofunction:: pydatastructs.radix_sort \ No newline at end of file diff --git a/pydatastructs/linear_data_structures/__init__.py b/pydatastructs/linear_data_structures/__init__.py index 057adc169..beb7cc82f 100644 --- a/pydatastructs/linear_data_structures/__init__.py +++ b/pydatastructs/linear_data_structures/__init__.py @@ -47,6 +47,7 @@ jump_search, selection_sort, insertion_sort, - intro_sort + intro_sort, + radix_sort ) __all__.extend(algorithms.__all__) diff --git a/pydatastructs/linear_data_structures/algorithms.py b/pydatastructs/linear_data_structures/algorithms.py index 792bce855..d32dba51a 100644 --- a/pydatastructs/linear_data_structures/algorithms.py +++ b/pydatastructs/linear_data_structures/algorithms.py @@ -30,7 +30,8 @@ 'jump_search', 'selection_sort', 'insertion_sort', - 'intro_sort' + 'intro_sort', + 'radix_sort', ] def _merge(array, sl, el, sr, er, end, comp): @@ -1850,3 +1851,73 @@ def partition(array, lower, upper): intro_sort(array, start=p+1, end=upper, maxdepth=maxdepth-1, ins_threshold=ins_threshold) return array + +def radix_sort(array, **kwargs): + """ + Implements Radix Sort. + + Parameters + ========== + + array: Array + The array which is to be sorted. + comp: lambda/function + The comparator which is to be used + for sorting. Optional, by default, less than or + equal to is used for comparing two + values. + """ + raise_if_backend_is_not_python(radix_sort, kwargs.get('backend', Backend.PYTHON)) + + start = kwargs.get('start', 0) + end = kwargs.get('end', len(array) - 1) + + sub_array = [] + none_indices = [] + max_val = 0 + + for i in range(start, end + 1): + if array[i] is not None: + sub_array.append(array[i]) + max_val = max(max_val, array[i]) + else: + none_indices.append(i) + + exp = 1 + while max_val // exp > 0: + n = len(sub_array) + output = [None] * n + count = [0] * 10 + + for i in range(n): + if sub_array[i] is not None: + index = (sub_array[i] // exp) % 10 + count[index] += 1 + + for i in range(1, 10): + count[i] += count[i - 1] + + i = n - 1 + while i >= 0: + if sub_array[i] is not None: + index = (sub_array[i] // exp) % 10 + output[count[index] - 1] = sub_array[i] + count[index] -= 1 + i -= 1 + + for i in range(n): + sub_array[i] = output[i] + + exp *= 10 + + sorted_array = sub_array[:] + for idx in none_indices: + sorted_array.insert(end, None) + + for i in range(start, end + 1): + array[i] = sorted_array[i - start] + + if _check_type(array, (DynamicArray, _arrays.DynamicOneDimensionalArray)): + array._modify(True) + + return array diff --git a/pydatastructs/linear_data_structures/tests/test_algorithms.py b/pydatastructs/linear_data_structures/tests/test_algorithms.py index 46609544b..42eccff9e 100644 --- a/pydatastructs/linear_data_structures/tests/test_algorithms.py +++ b/pydatastructs/linear_data_structures/tests/test_algorithms.py @@ -5,7 +5,7 @@ cocktail_shaker_sort, quick_sort, longest_common_subsequence, is_ordered, upper_bound, lower_bound, longest_increasing_subsequence, next_permutation, prev_permutation, bubble_sort, linear_search, binary_search, jump_search, - selection_sort, insertion_sort, intro_sort, Backend) + selection_sort, insertion_sort, intro_sort, radix_sort, Backend) from pydatastructs.utils.raises_util import raises import random @@ -94,6 +94,9 @@ def test_heapsort(): def test_bucket_sort(): _test_common_sort(bucket_sort) +def test_radix_sort(): + _test_common_sort(radix_sort) + def test_counting_sort(): random.seed(1000)