Skip to content

Commit 22f670c

Browse files
authored
Merge pull request #3 from maxicot/heapsort
Implement heapsort
2 parents 12a39a1 + a76937f commit 22f670c

File tree

7 files changed

+84
-0
lines changed

7 files changed

+84
-0
lines changed

.github/workflows/python.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ jobs:
1414
python -m pip install --upgrade pip
1515
pip install ruff
1616
pip install pytest
17+
pip install -r requirements.txt
1718
# Update output format to enable automatic inline annotations.
1819
- name: Run Ruff
1920
run: ruff check --output-format=github .

heapsort/__init__.py

Whitespace-only changes.

heapsort/src/lib.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from collections.abc import Callable
2+
from typing import TypeVar
3+
4+
T = TypeVar("T")
5+
6+
7+
# Recursive heapsort implementation.
8+
# The default behavior of `cmp` is to check
9+
# whether the first argument is smaller than the second.
10+
# A custom `cmp` is mandatory in case `T` doesn't support comparisons
11+
def heapsort(array: list, cmp: Callable[[T, T], bool] = lambda x, y: x < y) -> list:
12+
n = len(array)
13+
14+
if n < 2:
15+
return array
16+
17+
def heapify(array: list, n: int, i: int) -> list:
18+
left = 2 * i + 1
19+
right = left + 1
20+
largest = i
21+
22+
if left < n and cmp(array[largest], array[left]):
23+
largest = left
24+
25+
if right < n and cmp(array[largest], array[right]):
26+
largest = right
27+
28+
if largest != i:
29+
(array[i], array[largest]) = (array[largest], array[i])
30+
return heapify(array, n, largest)
31+
32+
return array
33+
34+
for i in range(n // 2, -1, -1):
35+
array = heapify(array, n, i)
36+
37+
for i in range(n - 1, 0, -1):
38+
(array[i], array[0]) = (array[0], array[i])
39+
array = heapify(array, i, 0)
40+
41+
return array

heapsort/tests/__init__.py

Whitespace-only changes.

heapsort/tests/test.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from hypothesis import given
2+
from hypothesis import strategies as st
3+
4+
from ..src.lib import heapsort
5+
6+
7+
def test_general():
8+
assert heapsort([0, 8, 3, -1, 5]) == [-1, 0, 3, 5, 8]
9+
assert heapsort([0, 8, 3, -1, 5], cmp=lambda x, y: x > y) == [8, 5, 3, 0, -1]
10+
11+
12+
def test_special():
13+
assert heapsort([]) == []
14+
assert heapsort([1]) == [1]
15+
16+
17+
@given(st.lists(st.integers(), max_size=100))
18+
def test_property(arr):
19+
assert heapsort(arr) == sorted(arr)
20+
21+
22+
class Custom:
23+
def __init__(self, n: int):
24+
self.inner = n
25+
26+
def __eq__(self, rhs) -> bool:
27+
return self.inner == rhs.inner
28+
29+
def into(self) -> int:
30+
return self.inner
31+
32+
33+
def test_custom():
34+
assert heapsort([Custom(2), Custom(1)], cmp=lambda x, y: x.inner < y.inner) == [
35+
Custom(1),
36+
Custom(2),
37+
]

pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,7 @@
1313
"RET", # Хорошие практики возврата
1414
"SIM", # Общие правила упрощения
1515
]
16+
17+
[tool.pytest.ini_options]
18+
python_files = "*.py"
19+
testpaths = ["./*/tests"]

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hypothesis

0 commit comments

Comments
 (0)