Skip to content

Commit 9d24425

Browse files
committed
Adding Shell Sort algorithm
1 parent da68ba5 commit 9d24425

File tree

6 files changed

+108
-2
lines changed

6 files changed

+108
-2
lines changed

README.md

+29
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ $ pip install py-algorithms
3636
- Binary Search
3737

3838
^ Sorting
39+
- Shell Sort (Shell method)
3940
- Heap Sort (Fibonacci heap)
4041
- Merge Sort
4142
- Bubble Sort
@@ -120,6 +121,7 @@ sorting_algorithm(xs)
120121

121122
#=> [-1, 0, 4, 5, 6, 7, 8, 9, 12]
122123
```
124+
123125
#### *Heap Sort (https://en.wikipedia.org/wiki/Heapsort)
124126

125127
In computer science, heapsort is a comparison-based sorting algorithm.
@@ -143,6 +145,33 @@ sorting_algorithm(xs)
143145

144146
#=> [-1, 0, 4, 5, 6, 7, 8, 9, 12]
145147
```
148+
149+
#### *Shell Sort (https://en.wikipedia.org/wiki/Shellsort)
150+
151+
Shellsort, also known as Shell sort or Shell's method, is an in-place comparison sort.
152+
It can be seen as either a generalization of sorting by exchange (bubble sort) or
153+
sorting by insertion (insertion sort). The method starts by sorting pairs of elements far apart
154+
from each other, then progressively reducing the gap between elements to be compared.
155+
Starting with far apart elements, it can move some out-of-place elements into position faster
156+
than a simple nearest neighbor exchange. Donald Shell published the first version of this sort in 1959
157+
The running time of Shellsort is heavily dependent on the gap sequence it uses. For many practical variants,
158+
determining their time complexity remains an open problem.
159+
160+
Worst case: О(n^2)
161+
Best case: О(n log n)
162+
Average: ~
163+
Worst case space: O(n)
164+
165+
```python
166+
from py_algorithms.sort import new_shell_sort
167+
168+
xs = [0, 6, 7, 8, 9, 4, 5, 12, -1]
169+
sorting_algorithm = new_shell_sort()
170+
sorting_algorithm(xs)
171+
172+
#=> [-1, 0, 4, 5, 6, 7, 8, 9, 12]
173+
```
174+
146175
---
147176

148177
### Search Algorithms

py_algorithms/sort/__init__.py

+17
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from ._heap_sort import FibonacciHeapSort
66
from ._merge_sort import RecursiveMergeSort
77
from ._selection_sort import SelectionSort
8+
from ._shell_sort import ShellSort
89
from .sort import Sort
910

1011
__all__ = [
@@ -74,3 +75,19 @@ def new_heap_sort() -> Callable[[List[int]], List[int]]:
7475
"""
7576

7677
return lambda xs: FibonacciHeapSort().sort(xs)
78+
79+
80+
def new_shell_sort() -> Callable[[List[int]], List[int]]:
81+
"""
82+
- Shell Sort algorithm. Factory method to return sort functor.
83+
84+
>>> from py_algorithms.sort import new_shell_sort
85+
>>>
86+
>>> xs = [0, 6, 7, 8, 9, 4, 5, 12, -1]
87+
>>> sorting_algorithm = new_heap_sort()
88+
>>> sorting_algorithm(xs) #=> [-1, 0, 4, 5, 6, 7, 8, 9, 12]
89+
90+
:return: a function1 interface to apply
91+
"""
92+
93+
return lambda xs: ShellSort().sort(xs)

py_algorithms/sort/_shell_sort.py

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from typing import List
2+
3+
from ..utils import test_iterable
4+
from .sort import Sort
5+
6+
7+
class ShellSort(Sort):
8+
"""
9+
Worst-case: О(n ^ 2)
10+
Best-case: O(n log n)
11+
Space: О(n)
12+
Stability: true
13+
"""
14+
15+
def sort(self, xs: List[int]) -> List[int]:
16+
test_iterable(xs)
17+
18+
inc = len(xs) // 2
19+
while inc > 0:
20+
for i in range(inc, len(xs)):
21+
temp = xs[i]
22+
j = i
23+
while j >= inc and xs[j - inc] > temp:
24+
xs[j] = xs[j - inc]
25+
j -= inc
26+
xs[j] = temp
27+
if inc == 2:
28+
inc = 1
29+
else:
30+
inc = int(round(inc // 2.2, 0))
31+
return xs

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
'fibonacci priority queue', 'max priority queue', 'min priority queue',
2424
'dynamic connectivity', 'union find', 'quick union', 'weighted quick union',
2525
'weighted quick union with path compression', 'fibonacci heap sort', 'heapsort',
26-
'heap sort'],
26+
'heap sort', 'shell-sort', 'shell sort'],
2727
description="Library of Algorithms, Data Structures, variety of solutions to common "
2828
"CS problems",
2929
long_description="Algorithms and Data Structures implemented using awesome Python.",

tests/conftest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ def xs() -> List[int]:
1111

1212
@pytest.fixture
1313
def large_xs() -> List[int]:
14-
raw = [0, 6, 7, 8, 9, 4, 5, 12, -112] * 50
14+
raw = [0, 6, 7, 8, 9, 4, 5, 12, -112] * 500
1515
random.shuffle(raw)
1616
return raw
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from typing import Callable
2+
from typing import List
3+
4+
import pytest
5+
6+
from py_algorithms.sort import new_shell_sort
7+
from tests.conftest import large_xs
8+
from tests.conftest import xs
9+
10+
11+
@pytest.fixture
12+
def new_sorting_algorithm() -> Callable[[List[int]], List[int]]:
13+
return new_shell_sort()
14+
15+
16+
class TestSelectionSort:
17+
def test_sorting_algorithm(self):
18+
f = new_sorting_algorithm()
19+
assert sorted(xs()) == f(xs())
20+
21+
def test_sorting_algorithm_on_large_xs(self):
22+
f = new_sorting_algorithm()
23+
assert sorted(large_xs()) == f(large_xs())
24+
25+
def test_non_iterable_xs(self):
26+
f = new_sorting_algorithm()
27+
for x in (None, 1, ''):
28+
with pytest.raises(RuntimeError):
29+
f(x)

0 commit comments

Comments
 (0)