Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/sorting_algorithms/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""
Пакет с алгоритмами сортировки:
- bubble_sort - Сортировка пузырьком
- merge_sort - Сортировка слиянием
- heap_sort - Сортировка кучей
- quick_sort - Быстрая сортировка
"""

from .bubble_sort import bubble_sort
from .heap_sort import heap_sort
from .merge_sort import merge_sort
from .quick_sort import quick_sort

__all__ = ["bubble_sort", "merge_sort", "heap_sort", "quick_sort"]
16 changes: 16 additions & 0 deletions src/sorting_algorithms/bubble_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
def bubble_sort(arr):
"""Сортировка пузырьком (Bubble sort)"""
if len(arr) <= 1:
return arr

n = len(arr)
for i in range(n - 1):
swapped = False
for j in range(n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
swapped = True
if not swapped:
break

return arr
38 changes: 38 additions & 0 deletions src/sorting_algorithms/heap_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
def heap_sort(arr):
"""Сортировка кучей (Heap Sort)"""
if len(arr) <= 1:
return arr

n = len(arr)

# Построение max-heap
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):
"""Вспомогательная функция для преобразования поддерева в max-heap"""

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
43 changes: 43 additions & 0 deletions src/sorting_algorithms/merge_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
def merge_sort(arr):
"""Сортировка слиянием (Merge sort)"""
if len(arr) <= 1:
return arr

temp = [0] * len(arr)
merge_sort_recursive(arr, temp, 0, len(arr) - 1)
return arr


def merge_sort_recursive(arr, temp, left, right):
"""Рекурсивная вспомогательная функция для сортировки слиянием"""
if left >= right:
return

mid = (left + right) // 2

merge_sort_recursive(arr, temp, left, mid)
merge_sort_recursive(arr, temp, mid + 1, right)

merge(arr, temp, left, mid, right)


def merge(arr, temp, left, mid, right):
"""Слияние двух отсортированных частей"""
i, j, k = left, mid + 1, left

for m in range(left, right + 1):
temp[m] = arr[m]

while i <= mid and j <= right:
if temp[i] <= temp[j]:
arr[k] = temp[i]
i += 1
else:
arr[k] = temp[j]
j += 1
k += 1

while i <= mid:
arr[k] = temp[i]
i += 1
k += 1
31 changes: 31 additions & 0 deletions src/sorting_algorithms/quick_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
def quick_sort(arr):
"""Быстрая сортировка (Quick Sort) - эффективная сортировка с разделением"""
if len(arr) <= 1:
return arr

quick_sort_recursive(arr, 0, len(arr) - 1)
return arr


def quick_sort_recursive(arr, low, high):
"""Рекурсивная часть быстрой сортировки"""
if low < high:
pivot_index = _partition(arr, low, high)

quick_sort_recursive(arr, low, pivot_index - 1)
quick_sort_recursive(arr, pivot_index + 1, high)


def _partition(arr, low, high):
"""Функция разделения массива - выбирает опорный элемент и переставляет другие (слева - < опорного, справа - > опорного)"""
pivot = arr[high]

i = low - 1

for j in range(low, high):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]

arr[i + 1], arr[high] = arr[high], arr[i + 1]
return i + 1
76 changes: 76 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""
Конфигурационный файл pytest с фикстурами
"""

import random

import pytest


@pytest.fixture
def empty_list():
"""Пустой список"""
return []


@pytest.fixture
def single_element_list():
"""Список с одним элементом"""
return [42]


@pytest.fixture
def sorted_list():
"""Отсортированный список"""
return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


@pytest.fixture
def reverse_sorted_list():
"""Обратно отсортированный список"""
return [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]


@pytest.fixture
def list_with_duplicates():
"""Список с повторяющимися элементами"""
return [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]


@pytest.fixture
def list_with_negatives():
"""Список с отрицательными числами"""
return [-5, -1, -3, -2, -4, 0, 2, 1, -6]


@pytest.fixture()
def random_list_small():
"""Маленький случайный список"""
random.seed(42)
return [random.randint(-100, 100) for _ in range(20)]


@pytest.fixture()
def random_list_large():
"""Большой случайный список"""
random.seed(42)
return [random.randint(-10000, 10000) for _ in range(1000)]


@pytest.fixture(params=[10, 100, 500])
def random_list_parametrized(request):
"""Списки разных размеров (параметризованная фикстура)"""
random.seed(request.param)
return [random.randint(-1000, 1000) for _ in range(request.param)]


@pytest.fixture
def edge_case_all_equal():
"""Спсиок из одинаковых элементов"""
return [7, 7, 7, 7, 7, 7, 7]


@pytest.fixture
def edge_case_floats():
"""Список из чисел с плавающей точкой"""
return [1.5, 2.3, 0.1, -1.2, 3.7, -0.5]
Loading