Skip to content

Commit dcf5aaa

Browse files
committed
Add Shell Sort algorithm (fixes #13887)
1 parent ae68a78 commit dcf5aaa

File tree

2 files changed

+59
-27
lines changed

2 files changed

+59
-27
lines changed

sorts/shell_sort.py

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,51 @@
11
"""
2-
https://en.wikipedia.org/wiki/Shellsort#Pseudocode
2+
Shell Sort Algorithm
3+
--------------------
4+
5+
Issue: #13887
6+
Implements the Shell Sort algorithm which is a generalization of insertion sort.
7+
It improves by comparing elements far apart, then reducing the gap between elements
8+
to be compared until the list is fully sorted.
9+
10+
Time Complexity:
11+
Worst case: O(n^2)
12+
Best case: O(n log n)
13+
Average: O(n^(3/2))
14+
15+
Space Complexity: O(1)
316
"""
417

18+
from __future__ import annotations
519

6-
def shell_sort(collection: list[int]) -> list[int]:
7-
"""Pure implementation of shell sort algorithm in Python
8-
:param collection: Some mutable ordered collection with heterogeneous
9-
comparable items inside
10-
:return: the same collection ordered by ascending
1120

12-
>>> shell_sort([0, 5, 3, 2, 2])
13-
[0, 2, 2, 3, 5]
21+
def shell_sort(arr: list[int]) -> list[int]:
22+
"""
23+
Sorts the given list using Shell Sort and returns the sorted list.
24+
25+
>>> shell_sort([5, 2, 9, 1])
26+
[1, 2, 5, 9]
1427
>>> shell_sort([])
1528
[]
16-
>>> shell_sort([-2, -5, -45])
17-
[-45, -5, -2]
29+
>>> shell_sort([3])
30+
[3]
31+
>>> shell_sort([1, 2, 3])
32+
[1, 2, 3]
33+
>>> shell_sort([4, 3, 3, 1])
34+
[1, 3, 3, 4]
1835
"""
19-
# Marcin Ciura's gap sequence
36+
n = len(arr)
37+
gap = n // 2
2038

21-
gaps = [701, 301, 132, 57, 23, 10, 4, 1]
22-
for gap in gaps:
23-
for i in range(gap, len(collection)):
24-
insert_value = collection[i]
39+
# Keep reducing the gap until it becomes 0
40+
while gap > 0:
41+
for i in range(gap, n):
42+
temp = arr[i]
2543
j = i
26-
while j >= gap and collection[j - gap] > insert_value:
27-
collection[j] = collection[j - gap]
44+
while j >= gap and arr[j - gap] > temp:
45+
arr[j] = arr[j - gap]
2846
j -= gap
29-
if j != i:
30-
collection[j] = insert_value
31-
return collection
32-
47+
arr[j] = temp
48+
gap //= 2
3349

34-
if __name__ == "__main__":
35-
from doctest import testmod
50+
return arr
3651

37-
testmod()
38-
user_input = input("Enter numbers separated by a comma:\n").strip()
39-
unsorted = [int(item) for item in user_input.split(",")]
40-
print(shell_sort(unsorted))

tests/sorts/test_shell_sort.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from sorts.shell_sort import shell_sort
2+
3+
4+
def test_shell_sort_basic():
5+
assert shell_sort([5, 2, 9, 1]) == [1, 2, 5, 9]
6+
7+
8+
def test_shell_sort_empty():
9+
assert shell_sort([]) == []
10+
11+
12+
def test_shell_sort_one_element():
13+
assert shell_sort([3]) == [3]
14+
15+
16+
def test_shell_sort_sorted():
17+
assert shell_sort([1, 2, 3, 4]) == [1, 2, 3, 4]
18+
19+
20+
def test_shell_sort_duplicates():
21+
assert shell_sort([4, 3, 3, 1]) == [1, 3, 3, 4]

0 commit comments

Comments
 (0)