diff --git a/AUTHORS b/AUTHORS index 943bf804d..8b5220bb7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -11,3 +11,4 @@ Pratik Goyal Jay Thorat Rajveer Singh Bharadwaj Kishan Ved +Arvinder Singh Dhoul \ No newline at end of file diff --git a/docs/source/pydatastructs/linear_data_structures/algorithms.rst b/docs/source/pydatastructs/linear_data_structures/algorithms.rst index 7ab521cfd..8cc871986 100644 --- a/docs/source/pydatastructs/linear_data_structures/algorithms.rst +++ b/docs/source/pydatastructs/linear_data_structures/algorithms.rst @@ -45,4 +45,8 @@ Algorithms .. autofunction:: pydatastructs.jump_search -.. autofunction:: pydatastructs.intro_sort \ No newline at end of file +.. autofunction:: pydatastructs.intro_sort + +.. autofunction:: pydatastructs.shell_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..de247b88e 100644 --- a/pydatastructs/linear_data_structures/__init__.py +++ b/pydatastructs/linear_data_structures/__init__.py @@ -47,6 +47,8 @@ jump_search, selection_sort, insertion_sort, - intro_sort + intro_sort, + shell_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..8b7295833 100644 --- a/pydatastructs/linear_data_structures/algorithms.py +++ b/pydatastructs/linear_data_structures/algorithms.py @@ -30,7 +30,9 @@ 'jump_search', 'selection_sort', 'insertion_sort', - 'intro_sort' + 'intro_sort', + 'shell_sort', + 'radix_sort' ] def _merge(array, sl, el, sr, er, end, comp): @@ -1850,3 +1852,157 @@ def partition(array, lower, upper): intro_sort(array, start=p+1, end=upper, maxdepth=maxdepth-1, ins_threshold=ins_threshold) return array + +def shell_sort(array, *args, **kwargs): + """ + Implements shell sort algorithm. + + Parameters + ========== + + array: Array + The array which is to be sorted. + start: int + The starting index of the portion + which is to be sorted. + Optional, by default 0 + end: int + The ending index of the portion which + is to be sorted. + Optional, by default the index + of the last position filled. + comp: lambda/function + The comparator which is to be used + for sorting. If the function returns + False then only swapping is performed. + Optional, by default, less than or + equal to is used for comparing two + values. + backend: pydatastructs.Backend + The backend to be used. + Optional, by default, the best available + backend is used. + + Returns + ======= + + output: Array + The sorted array. + + Examples + ======== + + >>> from pydatastructs.linear_data_structures.algorithms import OneDimensionalArray, shell_sort + >>> arr = OneDimensionalArray(int, [3, 2, 1]) + >>> out = shell_sort(arr) + >>> str(out) + '[1, 2, 3]' + >>> out = shell_sort(arr, comp=lambda u, v: u > v) + >>> str(out) + '[3, 2, 1]' + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Shellsort + """ + start = int(kwargs.get('start', 0)) + end = int(kwargs.get('end', len(array) - 1)) + comp = kwargs.get('comp', lambda u, v: u <= v) + + n = end - start + 1 + gap = n // 2 + while gap > 0: + for i in range(start + gap, end + 1): + temp = array[i] + j = i + while j >= start + gap and not _comp(array[j - gap], temp, comp): + array[j] = array[j - gap] + j -= gap + array[j] = temp + gap //= 2 + + if _check_type(array, (DynamicArray, _arrays.DynamicOneDimensionalArray)): + array._modify(True) + + return array + +def radix_sort(array, *args, **kwargs): + """ + Implements radix sort algorithm for non-negative integers. + + Parameters + ========== + + array: Array + The array which is to be sorted. Must contain non-negative integers. + start: int + The starting index of the portion + which is to be sorted. + Optional, by default 0 + end: int + The ending index of the portion which + is to be sorted. + Optional, by default the index + of the last position filled. + backend: pydatastructs.Backend + The backend to be used. + Optional, by default, the best available + backend is used. + + Returns + ======= + + output: Array + The sorted array. + + Examples + ======== + + >>> from pydatastructs.linear_data_structures.algorithms import OneDimensionalArray, radix_sort + >>> arr = OneDimensionalArray(int, [170, 45, 75, 90, 802, 24, 2, 66]) + >>> out = radix_sort(arr) + >>> str(out) + '[2, 24, 45, 66, 75, 90, 170, 802]' + + References + ========== + + .. [1] https://en.wikipedia.org/wiki/Radix_sort + """ + start = int(kwargs.get('start', 0)) + end = int(kwargs.get('end', len(array) - 1)) + + n = end - start + 1 + max_val = array[start] + for i in range(start + 1, end + 1): + if array[i] is not None and array[i] > max_val: + max_val = array[i] + exp = 1 + while max_val // exp > 0: + count = [0] * 10 + output = [None] * n + + for i in range(start, end + 1): + if array[i] is not None: + digit = (array[i] // exp) % 10 + count[digit] += 1 + + for i in range(1, 10): + count[i] += count[i - 1] + + for i in range(end, start - 1, -1): + if array[i] is not None: + digit = (array[i] // exp) % 10 + count[digit] -= 1 + output[count[digit]] = array[i] + + for i in range(n): + array[start + i] = output[i] + + exp *= 10 + + 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..dc6336b48 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, shell_sort, radix_sort, Backend) from pydatastructs.utils.raises_util import raises import random @@ -414,3 +414,9 @@ def test_binary_search(): def test_jump_search(): _test_common_search(jump_search) _test_common_search(jump_search, backend=Backend.CPP) + +def test_shell_sort(): + _test_common_sort(shell_sort) + +def test_radix_sort(): + _test_common_sort(radix_sort)