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
3 changes: 2 additions & 1 deletion .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10"]
python-version: [3.9, 3.11, 3.12]


steps:
- uses: actions/checkout@v4
Expand Down
6 changes: 6 additions & 0 deletions src/sorting_algorithms/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .bubble_sort import bubble_sort
from .quick_sort import quick_sort
from .heap_sort import heap_sort
from .merge_sort import merge_sort

__all__ = ['bubble_sort', 'quick_sort', 'heap_sort', 'merge_sort']
9 changes: 9 additions & 0 deletions src/sorting_algorithms/bubble_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
def bubble_sort(arr):
arr_copy = arr.copy()
n = len(arr_copy)
for i in range(n):
for j in range(0, n-i-1):
if arr_copy[j] > arr_copy[j+1]:
arr_copy[j], arr_copy[j+1] = arr_copy[j+1], arr_copy[j]
return arr_copy

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):
"""
Сортировка кучей
"""
n = len(arr)

# Строим кучу
for i in range(n // 2 - 1, -1, -1):
heap(arr, n, i)

# Извлекаем элементы
for i in range(n - 1, 0, -1):
arr[0], arr[i] = arr[i], arr[0] # Меняем корень с последним
heap(arr, i, 0) # Просеиваем новый корень

return arr


def heap(arr, n, i):
"""
Просеивание
"""
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:
arr[i], arr[largest] = arr[largest], arr[i] # Меняем местами
heap(arr, n, largest) # Просеиваем дальше
44 changes: 44 additions & 0 deletions src/sorting_algorithms/merge_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
def merge_sort(arr):
"""
Сортировка слиянием
"""
if len(arr) <= 1:
return arr.copy()

arr_copy = arr.copy()
_merge_sort_helper(arr_copy)
return arr_copy

def _merge_sort_helper(arr):
if len(arr) > 1:
mid = len(arr) // 2
left_half = arr[:mid]
right_half = arr[mid:]

# Рекурсивная сортировка обеих половин
_merge_sort_helper(left_half)
_merge_sort_helper(right_half)

i = j = k = 0

# Слияние отсортированных половин
while i < len(left_half) and j < len(right_half):
if left_half[i] < right_half[j]:
arr[k] = left_half[i]
i += 1
else:
arr[k] = right_half[j]
j += 1
k += 1

# Проверяем, не остались ли элементы в левой половине
while i < len(left_half):
arr[k] = left_half[i]
i += 1
k += 1

# Проверяем, не остались ли элементы в правой половине
while j < len(right_half):
arr[k] = right_half[j]
j += 1
k += 1
36 changes: 36 additions & 0 deletions src/sorting_algorithms/quick_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
def quick_sort(arr):
"""
Быстрая сортировка
"""
if len(arr) <= 1:
return arr

arr_copy = arr.copy()
_quick_sort_helper(arr_copy, 0, len(arr_copy) - 1)
return arr_copy

def _quick_sort_helper(arr, low, high):
if low < high:
# Индекс разделения
pi = _partition(arr, low, high)

# Рекурсивно сортируем элементы до и после разделения
_quick_sort_helper(arr, low, pi - 1)
_quick_sort_helper(arr, pi + 1, high)

def _partition(arr, low, high):
# Выбираем последний элемент как опорный
pivot = arr[high]

# Индекс меньшего элемента (указывает на правильную позицию pivot)
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
Empty file added tests/__init__.py
Empty file.
22 changes: 22 additions & 0 deletions tests/test_bubble_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from src.sorting_algorithms import bubble_sort

def test_empty_list():
assert bubble_sort([]) == []

def test_single_element():
assert bubble_sort([5]) == [5]

def test_sorted_list():
assert bubble_sort([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5]

def test_reverse_sorted():
assert bubble_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5]

def test_duplicate_elements():
assert bubble_sort([3, 1, 4, 1, 5, 9, 2, 6, 5]) == [1, 1, 2, 3, 4, 5, 5, 6, 9]

def test_negative_numbers():
assert bubble_sort([-3, -1, -4, -2]) == [-4, -3, -2, -1]

def test_mixed_numbers():
assert bubble_sort([3, -1, 0, -2, 5]) == [-2, -1, 0, 3, 5]
23 changes: 23 additions & 0 deletions tests/test_heap_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from src.sorting_algorithms import heap_sort

def test_empty_list():
assert heap_sort([]) == []

def test_single_element():
assert heap_sort([5]) == [5]

def test_sorted_list():
assert heap_sort([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5]

def test_reverse_sorted():
assert heap_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5]

def test_duplicate_elements():
assert heap_sort([3, 1, 4, 1, 5, 9, 2, 6, 5]) == [1, 1, 2, 3, 4, 5, 5, 6, 9]

def test_negative_numbers():
assert heap_sort([-3, -1, -4, -2]) == [-4, -3, -2, -1]

def test_mixed_numbers():
assert heap_sort([3, -1, 0, -2, 5]) == [-2, -1, 0, 3, 5]

23 changes: 23 additions & 0 deletions tests/test_merge_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from src.sorting_algorithms import merge_sort

def test_empty_list():
assert merge_sort([]) == []

def test_single_element():
assert merge_sort([5]) == [5]

def test_sorted_list():
assert merge_sort([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5]

def test_reverse_sorted():
assert merge_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5]

def test_duplicate_elements():
assert merge_sort([3, 1, 4, 1, 5, 9, 2, 6, 5]) == [1, 1, 2, 3, 4, 5, 5, 6, 9]

def test_negative_numbers():
assert merge_sort([-3, -1, -4, -2]) == [-4, -3, -2, -1]

def test_mixed_numbers():
assert merge_sort([3, -1, 0, -2, 5]) == [-2, -1, 0, 3, 5]

23 changes: 23 additions & 0 deletions tests/test_quick_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from src.sorting_algorithms import quick_sort

def test_empty_list():
assert quick_sort([]) == []

def test_single_element():
assert quick_sort([5]) == [5]

def test_sorted_list():
assert quick_sort([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5]

def test_reverse_sorted():
assert quick_sort([5, 4, 3, 2, 1]) == [1, 2, 3, 4, 5]

def test_duplicate_elements():
assert quick_sort([3, 1, 4, 1, 5, 9, 2, 6, 5]) == [1, 1, 2, 3, 4, 5, 5, 6, 9]

def test_negative_numbers():
assert quick_sort([-3, -1, -4, -2]) == [-4, -3, -2, -1]

def test_mixed_numbers():
assert quick_sort([3, -1, 0, -2, 5]) == [-2, -1, 0, 3, 5]