Skip to content

Commit e094f88

Browse files
committed
Added implementations of heap, merge, quich sorts. Built tests for heap sort.
1 parent bc0b6b1 commit e094f88

File tree

5 files changed

+244
-0
lines changed

5 files changed

+244
-0
lines changed

pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@ target-version = "py312"
1616
"RET", # Хорошие практики возврата
1717
"SIM", # Общие правила упрощения
1818
]
19+
20+
[tool.pytest.ini_options]
21+
testpaths = ["tests"]
22+
pythonpath = ["src"]

src/tests_pytest_6/heap_sort.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
def heapify(arr, n, i):
2+
largest = i
3+
left = 2 * i + 1
4+
right = 2 * i + 2
5+
6+
if left < n and arr[i] < arr[left]:
7+
largest = left
8+
9+
if right < n and arr[largest] < arr[right]:
10+
largest = right
11+
12+
if largest != i:
13+
arr[i], arr[largest] = arr[largest], arr[i]
14+
heapify(arr, n, largest)
15+
16+
17+
def heap_sort(arr):
18+
n = len(arr)
19+
20+
for i in range(n // 2 - 1, -1, -1):
21+
heapify(arr, n, i)
22+
23+
for i in range(n - 1, 0, -1):
24+
arr[i], arr[0] = arr[0], arr[i]
25+
26+
heapify(arr, i, 0)
27+
return arr

src/tests_pytest_6/merge_sort.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
def merge_sort(arr):
2+
if len(arr) > 1:
3+
mid = len(arr) // 2
4+
left = arr[:mid]
5+
right = arr[mid:]
6+
7+
merge_sort(left)
8+
merge_sort(right)
9+
10+
i = j = k = 0
11+
12+
while i < len(left) and j < len(right):
13+
if left[i] < right[j]:
14+
arr[k] = left[i]
15+
i += 1
16+
else:
17+
arr[k] = right[j]
18+
j += 1
19+
k += 1
20+
21+
while i < len(left):
22+
arr[k] = left[i]
23+
i += 1
24+
k += 1
25+
26+
while j < len(right):
27+
arr[k] = right[j]
28+
j += 1
29+
k += 1
30+
return arr

src/tests_pytest_6/quick_sort.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
def partition(array, start, end):
2+
pivot = array[start]
3+
low = start + 1
4+
high = end
5+
6+
while True:
7+
while low <= high and array[high] >= pivot:
8+
high = high - 1
9+
10+
while low <= high and array[low] <= pivot:
11+
low = low + 1
12+
13+
if low <= high:
14+
array[low], array[high] = array[high], array[low]
15+
else:
16+
break
17+
18+
array[start], array[high] = array[high], array[start]
19+
20+
return high
21+
22+
23+
def quick_sort(array, start=0, end=None):
24+
if end is None:
25+
end = len(array) - 1
26+
27+
if start >= end:
28+
return array
29+
30+
p = partition(array, start, end)
31+
quick_sort(array, start, p - 1)
32+
quick_sort(array, p + 1, end)
33+
return array
34+
35+
36+
def merge_sort(arr):
37+
if len(arr) > 1:
38+
mid = len(arr) // 2
39+
left = arr[:mid]
40+
right = arr[mid:]
41+
42+
merge_sort(left)
43+
merge_sort(right)
44+
45+
i = j = k = 0
46+
47+
while i < len(left) and j < len(right):
48+
if left[i] < right[j]:
49+
arr[k] = left[i]
50+
i += 1
51+
else:
52+
arr[k] = right[j]
53+
j += 1
54+
k += 1
55+
56+
while i < len(left):
57+
arr[k] = left[i]
58+
i += 1
59+
k += 1
60+
61+
while j < len(right):
62+
arr[k] = right[j]
63+
j += 1
64+
k += 1
65+
return arr

tests/test_heap_sort.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import random
2+
3+
import pytest
4+
from tests_pytest_6.heap_sort import heap_sort, heapify
5+
from tests_pytest_6.merge_sort import merge_sort
6+
from tests_pytest_6.quick_sort import quick_sort
7+
8+
# unit тесты
9+
10+
11+
def test_heapify_work():
12+
"""Тест функции heapify на корректность"""
13+
arr = [1, 3, 2]
14+
heapify(arr, 3, 0)
15+
assert arr == [3, 1, 2]
16+
17+
18+
def test_duplicate_elements():
19+
"""Тест с дубликатами"""
20+
assert heap_sort([3, 1, 2, 3, 1]) == [1, 1, 2, 3, 3]
21+
22+
23+
def test_negative_numbers():
24+
"""Тест с отрицательными числами"""
25+
assert heap_sort([-5, 3, -1, 0, 2]) == [-5, -1, 0, 2, 3]
26+
27+
28+
# крайние случаи
29+
30+
31+
def test_empty_list():
32+
"""Тест пустого списка"""
33+
assert heap_sort([]) == []
34+
35+
36+
def test_single_element():
37+
"""Тест одного элемента"""
38+
assert heap_sort([5]) == [5]
39+
40+
41+
def test_sorted_list():
42+
"""Тест уже отсортированного списка"""
43+
assert heap_sort([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5]
44+
45+
46+
def test_reverse_sorted():
47+
"""Тест обратно отсортированного списка"""
48+
assert heap_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5]
49+
50+
51+
def test_large_list():
52+
"""Тест большого списка"""
53+
lst = list(range(1000, 0, -1))
54+
expected = list(range(1, 1001))
55+
assert heap_sort(lst) == expected
56+
57+
58+
# параметризованный тест
59+
60+
61+
@pytest.mark.parametrize(
62+
"arr, expected",
63+
[([], []), ([5], [5]), ([3, 1], [1, 3]), ([3, 1, 5, 7], [1, 3, 5, 7])],
64+
)
65+
def test_heap_sort_main(arr, expected):
66+
assert heap_sort(arr) == expected
67+
68+
69+
# property-based тесты
70+
71+
72+
def test_property_idempotence():
73+
"""Повторная сортировка не меняет результат"""
74+
for _ in range(100):
75+
lst = [random.randint(-1000, 1000) for _ in range(random.randint(0, 100))]
76+
sorted_once = heap_sort(lst.copy())
77+
sorted_twice = heap_sort(sorted_once.copy())
78+
assert sorted_once == sorted_twice
79+
80+
81+
def test_property_length_preservation():
82+
"""Длина списка сохраняется"""
83+
for _ in range(100):
84+
lst = [random.randint(-1000, 1000) for _ in range(random.randint(0, 100))]
85+
assert len(heap_sort(lst)) == len(lst)
86+
87+
88+
def test_property_sorted_order():
89+
"""Результат должен быть отсортирован"""
90+
for _ in range(100):
91+
lst = [random.randint(-1000, 1000) for _ in range(random.randint(1, 100))]
92+
sorted_lst = heap_sort(lst)
93+
for i in range(1, len(sorted_lst)):
94+
assert sorted_lst[i - 1] <= sorted_lst[i]
95+
96+
97+
def test_against_builtin_sort():
98+
"""Сравнение со встроенной сортировкой Python"""
99+
for _ in range(100):
100+
lst = [random.randint(-1000, 1000) for _ in range(random.randint(0, 100))]
101+
assert heap_sort(lst.copy()) == sorted(lst)
102+
103+
104+
# Сравнение с другими сортировками
105+
106+
107+
def test_against_quick_sort():
108+
"""Сравнение с quick_sort"""
109+
for _ in range(50):
110+
lst = [random.randint(-100, 100) for _ in range(random.randint(0, 50))]
111+
assert heap_sort(lst.copy()) == quick_sort(lst.copy())
112+
113+
114+
def test_against_merge_sort():
115+
"""Сравнение с merge_sort"""
116+
for _ in range(50):
117+
lst = [random.randint(-100, 100) for _ in range(random.randint(0, 50))]
118+
assert heap_sort(lst.copy()) == merge_sort(lst.copy())

0 commit comments

Comments
 (0)