Skip to content

Commit f7a6296

Browse files
authored
Implement shell_sort and radix_sort (#661)
1 parent 4d1116d commit f7a6296

File tree

5 files changed

+173
-4
lines changed

5 files changed

+173
-4
lines changed

AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ Pratik Goyal <[email protected]>
1111
Jay Thorat <[email protected]>
1212
Rajveer Singh Bharadwaj <[email protected]>
1313
Kishan Ved <[email protected]>
14+
Arvinder Singh Dhoul <[email protected]>

docs/source/pydatastructs/linear_data_structures/algorithms.rst

+5-1
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,8 @@ Algorithms
4545

4646
.. autofunction:: pydatastructs.jump_search
4747

48-
.. autofunction:: pydatastructs.intro_sort
48+
.. autofunction:: pydatastructs.intro_sort
49+
50+
.. autofunction:: pydatastructs.shell_sort
51+
52+
.. autofunction:: pydatastructs.radix_sort

pydatastructs/linear_data_structures/__init__.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
jump_search,
4848
selection_sort,
4949
insertion_sort,
50-
intro_sort
50+
intro_sort,
51+
shell_sort,
52+
radix_sort
5153
)
5254
__all__.extend(algorithms.__all__)

pydatastructs/linear_data_structures/algorithms.py

+157-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
'jump_search',
3131
'selection_sort',
3232
'insertion_sort',
33-
'intro_sort'
33+
'intro_sort',
34+
'shell_sort',
35+
'radix_sort'
3436
]
3537

3638
def _merge(array, sl, el, sr, er, end, comp):
@@ -1850,3 +1852,157 @@ def partition(array, lower, upper):
18501852
intro_sort(array, start=p+1, end=upper, maxdepth=maxdepth-1, ins_threshold=ins_threshold)
18511853

18521854
return array
1855+
1856+
def shell_sort(array, *args, **kwargs):
1857+
"""
1858+
Implements shell sort algorithm.
1859+
1860+
Parameters
1861+
==========
1862+
1863+
array: Array
1864+
The array which is to be sorted.
1865+
start: int
1866+
The starting index of the portion
1867+
which is to be sorted.
1868+
Optional, by default 0
1869+
end: int
1870+
The ending index of the portion which
1871+
is to be sorted.
1872+
Optional, by default the index
1873+
of the last position filled.
1874+
comp: lambda/function
1875+
The comparator which is to be used
1876+
for sorting. If the function returns
1877+
False then only swapping is performed.
1878+
Optional, by default, less than or
1879+
equal to is used for comparing two
1880+
values.
1881+
backend: pydatastructs.Backend
1882+
The backend to be used.
1883+
Optional, by default, the best available
1884+
backend is used.
1885+
1886+
Returns
1887+
=======
1888+
1889+
output: Array
1890+
The sorted array.
1891+
1892+
Examples
1893+
========
1894+
1895+
>>> from pydatastructs.linear_data_structures.algorithms import OneDimensionalArray, shell_sort
1896+
>>> arr = OneDimensionalArray(int, [3, 2, 1])
1897+
>>> out = shell_sort(arr)
1898+
>>> str(out)
1899+
'[1, 2, 3]'
1900+
>>> out = shell_sort(arr, comp=lambda u, v: u > v)
1901+
>>> str(out)
1902+
'[3, 2, 1]'
1903+
1904+
References
1905+
==========
1906+
1907+
.. [1] https://en.wikipedia.org/wiki/Shellsort
1908+
"""
1909+
start = int(kwargs.get('start', 0))
1910+
end = int(kwargs.get('end', len(array) - 1))
1911+
comp = kwargs.get('comp', lambda u, v: u <= v)
1912+
1913+
n = end - start + 1
1914+
gap = n // 2
1915+
while gap > 0:
1916+
for i in range(start + gap, end + 1):
1917+
temp = array[i]
1918+
j = i
1919+
while j >= start + gap and not _comp(array[j - gap], temp, comp):
1920+
array[j] = array[j - gap]
1921+
j -= gap
1922+
array[j] = temp
1923+
gap //= 2
1924+
1925+
if _check_type(array, (DynamicArray, _arrays.DynamicOneDimensionalArray)):
1926+
array._modify(True)
1927+
1928+
return array
1929+
1930+
def radix_sort(array, *args, **kwargs):
1931+
"""
1932+
Implements radix sort algorithm for non-negative integers.
1933+
1934+
Parameters
1935+
==========
1936+
1937+
array: Array
1938+
The array which is to be sorted. Must contain non-negative integers.
1939+
start: int
1940+
The starting index of the portion
1941+
which is to be sorted.
1942+
Optional, by default 0
1943+
end: int
1944+
The ending index of the portion which
1945+
is to be sorted.
1946+
Optional, by default the index
1947+
of the last position filled.
1948+
backend: pydatastructs.Backend
1949+
The backend to be used.
1950+
Optional, by default, the best available
1951+
backend is used.
1952+
1953+
Returns
1954+
=======
1955+
1956+
output: Array
1957+
The sorted array.
1958+
1959+
Examples
1960+
========
1961+
1962+
>>> from pydatastructs.linear_data_structures.algorithms import OneDimensionalArray, radix_sort
1963+
>>> arr = OneDimensionalArray(int, [170, 45, 75, 90, 802, 24, 2, 66])
1964+
>>> out = radix_sort(arr)
1965+
>>> str(out)
1966+
'[2, 24, 45, 66, 75, 90, 170, 802]'
1967+
1968+
References
1969+
==========
1970+
1971+
.. [1] https://en.wikipedia.org/wiki/Radix_sort
1972+
"""
1973+
start = int(kwargs.get('start', 0))
1974+
end = int(kwargs.get('end', len(array) - 1))
1975+
1976+
n = end - start + 1
1977+
max_val = array[start]
1978+
for i in range(start + 1, end + 1):
1979+
if array[i] is not None and array[i] > max_val:
1980+
max_val = array[i]
1981+
exp = 1
1982+
while max_val // exp > 0:
1983+
count = [0] * 10
1984+
output = [None] * n
1985+
1986+
for i in range(start, end + 1):
1987+
if array[i] is not None:
1988+
digit = (array[i] // exp) % 10
1989+
count[digit] += 1
1990+
1991+
for i in range(1, 10):
1992+
count[i] += count[i - 1]
1993+
1994+
for i in range(end, start - 1, -1):
1995+
if array[i] is not None:
1996+
digit = (array[i] // exp) % 10
1997+
count[digit] -= 1
1998+
output[count[digit]] = array[i]
1999+
2000+
for i in range(n):
2001+
array[start + i] = output[i]
2002+
2003+
exp *= 10
2004+
2005+
if _check_type(array, (DynamicArray, _arrays.DynamicOneDimensionalArray)):
2006+
array._modify(True)
2007+
2008+
return array

pydatastructs/linear_data_structures/tests/test_algorithms.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
cocktail_shaker_sort, quick_sort, longest_common_subsequence, is_ordered,
66
upper_bound, lower_bound, longest_increasing_subsequence, next_permutation,
77
prev_permutation, bubble_sort, linear_search, binary_search, jump_search,
8-
selection_sort, insertion_sort, intro_sort, Backend)
8+
selection_sort, insertion_sort, intro_sort, shell_sort, radix_sort, Backend)
99

1010
from pydatastructs.utils.raises_util import raises
1111
import random
@@ -414,3 +414,9 @@ def test_binary_search():
414414
def test_jump_search():
415415
_test_common_search(jump_search)
416416
_test_common_search(jump_search, backend=Backend.CPP)
417+
418+
def test_shell_sort():
419+
_test_common_sort(shell_sort)
420+
421+
def test_radix_sort():
422+
_test_common_sort(radix_sort)

0 commit comments

Comments
 (0)