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
38 changes: 38 additions & 0 deletions src/homework5_17.10_tests-sort/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) # Просеиваем дальше
50 changes: 50 additions & 0 deletions src/homework5_17.10_tests-sort/other_sorts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# other_sorts.py

def bubble_sort(arr):
"""
Пузырьковая сортировка
"""
if not arr:
return arr.copy()

arr = arr.copy() # Работаем с копией, чтобы не менять оригинал
n = len(arr)

# Проходим по массиву n раз
for i in range(n):
# Сравниваем соседние элементы
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
# Меняем местами, если нужно
arr[j], arr[j + 1] = arr[j + 1], arr[j]

return arr

def selection_sort(arr):
"""
Сортировка выбором - ищем минимальный элемент и ставим на правильное место
"""
if not arr:
return arr.copy()

arr = arr.copy()
n = len(arr)

for i in range(n):
# Предполагаем, что текущий элемент - минимальный
min_index = i

# Ищем настоящий минимальный элемент в оставшейся части
for j in range(i + 1, n):
if arr[j] < arr[min_index]:
min_index = j

# Меняем местами с текущим элементом
arr[i], arr[min_index] = arr[min_index], arr[i]

return arr

# Встроенная сортировка Python для сравнения
def python_sort(arr):
"""Используем встроенную сортировку как эталон"""
return sorted(arr.copy())
73 changes: 73 additions & 0 deletions src/homework5_17.10_tests-sort/test_heap_sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# test_heap_sort.py
import pytest
from heap_sort import heap_sort

# простые тесты

def test_basic_sort():
"""Самый простой тест - обычный случай"""
arr = [4, 2, 8, 1, 5]
result = heap_sort(arr.copy())
assert result == [1, 2, 4, 5, 8]

def test_already_sorted():
"""Тест с уже отсортированным массивом"""
arr = [1, 2, 3, 4, 5]
result = heap_sort(arr.copy())
assert result == [1, 2, 3, 4, 5]

def test_reverse_sorted():
"""Тест с обратным порядком"""
arr = [5, 4, 3, 2, 1]
result = heap_sort(arr.copy())
assert result == [1, 2, 3, 4, 5]

# Тесты крайних случаев

def test_empty_array():
"""Тест пустого массива"""
arr = []
result = heap_sort(arr.copy())
assert result == []

def test_single_element():
"""Тест с одним элементом"""
arr = [42]
result = heap_sort(arr.copy())
assert result == [42]

def test_two_elements():
"""Тест с двумя элементами"""
# Уже отсортирован
assert heap_sort([1, 2]) == [1, 2]
# Не отсортирован
assert heap_sort([2, 1]) == [1, 2]

def test_all_same_elements():
"""Тест когда все элементы одинаковые"""
arr = [5, 5, 5, 5, 5]
result = heap_sort(arr.copy())
assert result == [5, 5, 5, 5, 5]

# 3. Тесты с особенными данными

def test_with_duplicates():
"""Тест с повторяющимися числами"""
arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]
result = heap_sort(arr.copy())
expected = [1, 1, 2, 3, 3, 4, 5, 5, 6, 9]
assert result == expected

def test_negative_numbers():
"""Тест с отрицательными числами"""
arr = [-3, -1, -5, 0, 2, -2]
result = heap_sort(arr.copy())
expected = [-5, -3, -2, -1, 0, 2]
assert result == expected

def test_mixed_numbers():
"""Тест со смешанными числами"""
arr = [10, -5, 0, 3, -2, 7]
result = heap_sort(arr.copy())
expected = [-5, -2, 0, 3, 7, 10]
assert result == expected
130 changes: 130 additions & 0 deletions src/homework5_17.10_tests-sort/tests2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# tests2.py
import pytest
import random
from other_sorts import bubble_sort, selection_sort, python_sort
from heap_sort import heap_sort

# 1. Основное свойство: ВСЕ ТРИ сортировки дают одинаковый результат

def test_all_three_sorts_same_result_simple():
"""Все три сортировки дают одинаковый результат на простом массиве"""
arr = [4, 2, 8, 1, 5]

bubble_result = bubble_sort(arr)
selection_result = selection_sort(arr)
heap_result = heap_sort(arr)
python_result = python_sort(arr)

# Все должны быть равны
assert bubble_result == selection_result == heap_result == python_result
assert heap_result == [1, 2, 4, 5, 8]

def test_all_three_sorts_same_result_random():
"""Тестируем на случайных массивах разного размера"""
for size in [5, 10, 15, 20, 25]:
arr = [random.randint(1, 100) for _ in range(size)]

bubble_result = bubble_sort(arr)
selection_result = selection_sort(arr)
heap_result = heap_sort(arr)
python_result = python_sort(arr)

# Проверяем что все результаты одинаковые
assert bubble_result == selection_result == heap_result == python_result

# И что результат отсортирован
for i in range(len(bubble_result) - 1):
assert bubble_result[i] <= bubble_result[i + 1]

# 2. Свойство: идемпотентность всех трёх сортировок

def test_idempotence_all_three():
"""Все три сортировки идемпотентны"""
arr = [random.randint(1, 50) for _ in range(10)]

# Тестируем каждую сортировку
for sort_func in [bubble_sort, selection_sort, heap_sort]:
first_sort = sort_func(arr)
second_sort = sort_func(first_sort)

# Должны получить тот же результат
assert first_sort == second_sort, f"Сортировка {sort_func.__name__} не идемпотентна"

def test_idempotence_cross_check():
"""Перекрёстная проверка идемпотентности"""
arr = [3, 1, 4, 1, 5, 9, 2, 6]

bubble_once = bubble_sort(arr)
bubble_twice = bubble_sort(bubble_once)

selection_once = selection_sort(arr)
selection_twice = selection_sort(selection_once)

heap_once = heap_sort(arr)
heap_twice = heap_sort(heap_once)

# Все должны быть равны после повторной сортировки
assert bubble_once == bubble_twice
assert selection_once == selection_twice
assert heap_once == heap_twice
assert bubble_once == selection_once == heap_once

# 3. Свойство: сохранение элементов во всех трёх сортировках

def test_preserves_all_elements_all_three():
"""Все три сортировки сохраняют все элементы"""
arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]

bubble_result = bubble_sort(arr)
selection_result = selection_sort(arr)
heap_result = heap_sort(arr)

# Проверяем что все содержат одинаковые элементы
assert set(arr) == set(bubble_result) == set(selection_result) == set(heap_result)
assert len(arr) == len(bubble_result) == len(selection_result) == len(heap_result)

# Проверяем количество каждого элемента
for num in set(arr):
original_count = arr.count(num)
assert original_count == bubble_result.count(num)
assert original_count == selection_result.count(num)
assert original_count == heap_result.count(num)

# 4. Свойство: работа с разными типами данных

def test_negative_numbers_all_three():
"""Все три сортировки работают с отрицательными числами"""
arr = [-3, -1, -5, 0, 2, -2, 7, -8, 4, -1]

bubble_result = bubble_sort(arr)
selection_result = selection_sort(arr)
heap_result = heap_sort(arr)
python_result = python_sort(arr)

expected = [-8, -5, -3, -2, -1, -1, 0, 2, 4, 7]

assert bubble_result == expected
assert selection_result == expected
assert heap_result == expected
assert python_result == expected

def test_duplicates_all_three():
"""Все три сортировки корректно обрабатывают дубликаты"""
arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 1]

bubble_result = bubble_sort(arr)
selection_result = selection_sort(arr)
heap_result = heap_sort(arr)

# Все должны дать одинаковый результат с дубликатами
assert bubble_result == selection_result == heap_result

# Проверяем что дубликаты на месте
assert bubble_result.count(1) == 3
assert bubble_result.count(3) == 2
assert bubble_result.count(5) == 3