From 712fedbea812ec5813eb24c889c247239e8aa700 Mon Sep 17 00:00:00 2001 From: asmit27rai Date: Thu, 13 Mar 2025 13:08:01 +0530 Subject: [PATCH 1/2] feat: Add Radix Sort Algorithm Added an implementation of the Radix Sort algorithm. Radix Sort is a non-comparative sorting algorithm that sorts numbers digit by digit, typically using Counting Sort as a subroutine. This implementation sorts numbers starting from the least significant digit (LSD). --- .../linear_data_structures/algorithms.rst | 4 +- .../linear_data_structures/__init__.py | 3 +- .../linear_data_structures/algorithms.py | 71 ++++++++++++++++++- .../tests/test_algorithms.py | 5 +- 4 files changed, 79 insertions(+), 4 deletions(-) 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..aa0ad31db 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,71 @@ 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) From 2aa34e39425f043b5f85c080be8a1276b5dfb0e6 Mon Sep 17 00:00:00 2001 From: asmit27rai Date: Wed, 19 Mar 2025 13:37:28 +0530 Subject: [PATCH 2/2] fix --- pydatastructs/linear_data_structures/algorithms.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pydatastructs/linear_data_structures/algorithms.py b/pydatastructs/linear_data_structures/algorithms.py index aa0ad31db..d32dba51a 100644 --- a/pydatastructs/linear_data_structures/algorithms.py +++ b/pydatastructs/linear_data_structures/algorithms.py @@ -1855,8 +1855,10 @@ def partition(array, lower, upper): def radix_sort(array, **kwargs): """ Implements Radix Sort. + Parameters ========== + array: Array The array which is to be sorted. comp: lambda/function