diff --git a/.github/workflows/heapsort-tests.yml b/.github/workflows/heapsort-tests.yml new file mode 100644 index 0000000..f5d5844 --- /dev/null +++ b/.github/workflows/heapsort-tests.yml @@ -0,0 +1,23 @@ +name: Run Heap Sort Tests + +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.13' + + - name: Install pytest + run: pip install pytest + + - name: Run tests + run: | + python -m pytest tests/tests_heapsort.py -v + diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/__init__.py @@ -0,0 +1 @@ + diff --git a/src/hw_heapsort/__init__.py b/src/hw_heapsort/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/hw_heapsort/__init__.py @@ -0,0 +1 @@ + diff --git a/src/hw_heapsort/sorts.py b/src/hw_heapsort/sorts.py new file mode 100644 index 0000000..f79e98a --- /dev/null +++ b/src/hw_heapsort/sorts.py @@ -0,0 +1,52 @@ +def heap_sort(arr): + if len(arr) <= 1: + return arr + + n = len(arr) + for i in range(n // 2 - 1, -1, -1): + heapify(arr, n, i) + + for i in range(n - 1, 0, -1): + arr[0], arr[i] = arr[i], arr[0] + heapify(arr, i, 0) + + return arr + + +def heapify(arr, n, i): + while True: + largest = i + left = 2 * i + 1 + right = 2 * i + 2 + + if left < n and arr[left] > arr[largest]: + largest = left + + if right < n and arr[right] > arr[largest]: + largest = right + + if largest == i: + break + + arr[i], arr[largest] = arr[largest], arr[i] + i = largest + + +def bubble_sort(arr): + n = len(arr) + for i in range(n - 1): + for j in range(n - i - 1): + if arr[j] > arr[j + 1]: + arr[j], arr[j + 1] = arr[j + 1], arr[j] + return arr + + +def insertion_sort(arr): + for i in range(1, len(arr)): + key = arr[i] + j = i - 1 + while j >= 0 and arr[j] > key: + arr[j + 1] = arr[j] + j -= 1 + arr[j + 1] = key + return arr diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/tests_heapsort.py b/tests/tests_heapsort.py new file mode 100644 index 0000000..0bc6d3a --- /dev/null +++ b/tests/tests_heapsort.py @@ -0,0 +1,136 @@ +import pytest +from src.hw_heapsort.sorts import heap_sort, bubble_sort, insertion_sort + +# обычные unit тесты и крайние случаи +@pytest.mark.empty +def test_heap_sort_empty(): + """Тест для пустого списка""" + result = heap_sort([]) + assert result == [] + + +@pytest.mark.single +def test_heap_sort_single(): + """Тест для списка из одного элемента""" + result = heap_sort([42]) + assert result == [42] + + +@pytest.mark.sorted +def test_heap_sort_sorted(): + """Тест для уже отсортированного списка""" + result = heap_sort([1, 2, 3, 4, 5]) + assert result == [1, 2, 3, 4, 5] + + +@pytest.mark.reversed +def test_heap_sort_reversed(): + """Тест для списка, отсортированного в обратном порядке""" + result = heap_sort([5, 4, 3, 2, 1]) + assert result == [1, 2, 3, 4, 5] + + +@pytest.mark.duplicates +def test_heap_sort_with_duplicates(): + """Тест для списка с дубликатами""" + result = heap_sort([1, 3, 1, 3, 2, 1, 1, 1, 2]) + assert result == [1, 1, 1, 1, 1, 2, 2, 3, 3] + +@pytest.mark.negative +def test_heap_sort_negative_num(): + """Тест с отрицательными числами""" + result = heap_sort([-5, -1, -3, -2, -181818, -4]) + assert result == [-181818, -5, -4, -3, -2, -1] + + +@pytest.mark.mixed +def test_heap_sort_mixed(): + """Тест с положительными и отрицательными числами""" + result = heap_sort([250000, -3, 5, -1, 2, -1000, 0, -2]) + assert result == [-1000, -3, -2, -1, 0, 2, 5, 250000] + + +@pytest.mark.float +def test_heap_sort_floats(): + """Тест с числами с плавающей точкой""" + result = heap_sort([3.6, 1.2, 4.8, 2.1, 0.5, 2.0]) + assert result == [0.5, 1.2, 2.0, 2.1, 3.6, 4.8] + +# тесты для сравнения heapsort и insertion sort и bubble sort +@pytest.mark.all_sorts_empty +def test_all_sorts_empty(): + """Тест для пустого списка""" + heap_result = heap_sort([]) + insertion_result = insertion_sort([]) + bubble_result = bubble_sort([]) + python_result = sorted([]) + assert heap_result == insertion_result == bubble_result == python_result + + +@pytest.mark.all_sorts_single +def test_all_sorts_single(): + """Тест для списка из одного элемента""" + heap_result = heap_sort([52]) + insertion_result = insertion_sort([52]) + bubble_result = bubble_sort([52]) + python_result = sorted([52]) + assert heap_result == insertion_result == bubble_result == python_result + + +@pytest.mark.all_sorts_sorted +def test_all_sorts_sorted(): + """Тест для уже отсортированного списка""" + heap_result = heap_sort([1,2,3]) + insertion_result = insertion_sort([1,2,3]) + bubble_result = bubble_sort([1,2,3]) + python_result = sorted([1,2,3]) + assert heap_result == insertion_result == bubble_result == python_result + + +@pytest.mark.all_sorts_reversed +def test_all_sorts_reversed(): + """Тест для списка, отсортированного в обратном порядке""" + heap_result = heap_sort([5, 4, 3]) + insertion_result = insertion_sort([5, 4, 3]) + bubble_result = bubble_sort([5, 4, 3]) + python_result = sorted([5, 4, 3]) + assert heap_result == insertion_result == bubble_result == python_result + + +@pytest.mark.all_sorts_duplicates +def test_all_sorts_with_duplicates(): + """Тест для списка с дубликатами""" + heap_result = heap_sort([0, 0, 3, 5, 4, 5, 5, 3, 0, 0]) + insertion_result = insertion_sort([0, 0, 3, 5, 4, 5, 5, 3, 0, 0]) + bubble_result = bubble_sort([0, 0, 3, 5, 4, 5, 5, 3, 0, 0]) + python_result = sorted([0, 0, 3, 5, 4, 5, 5, 3, 0, 0]) + assert heap_result == insertion_result == bubble_result == python_result + +@pytest.mark.all_sorts_negative +def test_all_sorts_negative_num(): + """Тест с отрицательными числами""" + heap_result = heap_sort([-762, -10, -387, -37072]) + insertion_result = insertion_sort([-762, -10, -387, -37072]) + bubble_result = bubble_sort([-762, -10, -387, -37072]) + python_result = sorted([-762, -10, -387, -37072]) + assert heap_result == insertion_result == bubble_result == python_result + + +@pytest.mark.all_sorts_mixed +def test_all_sorts_mixed(): + """Тест с положительными и отрицательными числами""" + heap_result = heap_sort([100, -1, 0, -387, 153]) + insertion_result = insertion_sort([100, -1, 0, -387, 153]) + bubble_result = bubble_sort([100, -1, 0, -387, 153]) + python_result = sorted([100, -1, 0, -387, 153]) + assert heap_result == insertion_result == bubble_result == python_result + + +@pytest.mark.all_sorts_float +def test_all_sorts_floats(): + """Тест с числами с плавающей точкой""" + heap_result = heap_sort([1.0, -1.9, 0.0, -3.8, 153.5]) + insertion_result = insertion_sort([1.0, -1.9, 0.0, -3.8, 153.5]) + bubble_result = bubble_sort([1.0, -1.9, 0.0, -3.8, 153.5]) + python_result = sorted([1.0, -1.9, 0.0, -3.8, 153.5]) + assert heap_result == insertion_result == bubble_result == python_result