-
Notifications
You must be signed in to change notification settings - Fork 0
Домашнее задание 6.1. Heap sort. Разгуляева А.И. #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| # ruff.toml | ||
| target-version = "py311" | ||
| line-length = 100 | ||
|
|
||
| # включить все основные правила | ||
| select = [ | ||
| "E", # pycodestyle errors | ||
| "W", # pycodestyle warnings | ||
| "F", # Pyflakes | ||
| "I", # isort | ||
| "N", # pep8-naming | ||
| "UP", # pyupgrade | ||
| "YTT", # flake8-2020 | ||
| "S", # flake8-bandit | ||
| "A", # flake8-builtins | ||
| "COM", # flake8-commas | ||
| "C4", # flake8-comprehensions | ||
| "DTZ", # flake8-datetimez | ||
| "T10", # flake8-debugger | ||
| "EM", # flake8-errmsg | ||
| "EXE", # flake8-executable | ||
| "ISC", # flake8-implicit-str-concat | ||
| "ICN", # flake8-import-conventions | ||
| "G", # flake8-logging-format | ||
| "INP", # flake8-no-pep420 | ||
| "PIE", # flake8-pie | ||
| "T20", # flake8-print | ||
| "PYI", # flake8-pyi | ||
| "PT", # flake8-pytest-style | ||
| "Q", # flake8-quotes | ||
| "RSE", # flake8-raise | ||
| "RET", # flake8-return | ||
| "SLF", # flake8-self | ||
| "SIM", # flake8-simplify | ||
| "TID", # flake8-tidy-imports | ||
| "TCH", # flake8-type-checking | ||
| "INT", # flake8-gettext | ||
| "ARG", # flake8-unused-arguments | ||
| "FBT", # flake8-boolean-trap | ||
| "B", # flake8-bugbear | ||
| "AIR", # flake8-airflow | ||
| "PERF", # flake8-perflint | ||
| ] | ||
|
|
||
| # игнорировать правила | ||
| ignore = [ | ||
| "E501", # line too long - handled by formatter | ||
| "S101", # assert used - ok in tests | ||
| "T201", # print found - sometimes needed | ||
| "COM812", # trailing comma missing - not always required | ||
| ] | ||
|
|
||
| # настройки для конкретных файлов | ||
| [per-file-ignores] | ||
| "__init__.py" = ["F401"] # Unused imports allowed in __init__.py | ||
| "tests/**" = ["S101", "SLF001"] # Allow assert and self in tests | ||
| "**/migrations/**" = ["ALL"] # Ignore all in migrations | ||
|
|
||
| # настройки форматтера | ||
| [format] | ||
| indent-style = "space" | ||
| quote-style = "double" | ||
| skip-magic-trailing-comma = false | ||
| line-ending = "auto" | ||
|
|
||
| # настройки для конкретных правил | ||
| [flake8-quotes] | ||
| docstring-quotes = "double" | ||
| inline-quotes = "double" | ||
|
|
||
| [flake8-tidy-imports] | ||
| ban-relative-imports = "all" | ||
|
|
||
| [isort] | ||
| known-first-party = ["myapp"] | ||
| lines-after-imports = 2 | ||
| combine-as-imports = true | ||
| split-on-trailing-comma = true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| # преобразование в двоичную кучу с корнем i (индекс в arr); n - размер кучи | ||
| def heapify(arr, n, i): | ||
| largest = i | ||
| l = 2 * i + 1 # left | ||
| r = 2 * i + 2 # right | ||
|
|
||
| # проверяем существует ли левый дочерний элемент больший, чем корень | ||
| if l < n and arr[i] < arr[l]: | ||
| largest = l | ||
|
|
||
| # проверяем существует ли правый дочерний элемент больший, чем корень | ||
| if r < n and arr[largest] < arr[r]: | ||
| largest = r | ||
|
|
||
| # заменяем корень, если нашёлся элемент больше | ||
| if largest != i: | ||
| arr[i], arr[largest] = arr[largest], arr[i] | ||
|
|
||
| # применяем heapify к корню | ||
| heapify(arr, n, largest) | ||
|
|
||
|
|
||
| # сортировка массива (основная функция) | ||
| def heap_sort(arr): | ||
| n = len(arr) | ||
|
|
||
| # строим max-heap | ||
| for i in range(n, -1, -1): | ||
| heapify(arr, n, i) | ||
|
|
||
| # переворачиваем массив | ||
| for i in range(n - 1, 0, -1): | ||
| arr[i], arr[0] = arr[0], arr[i] # свап | ||
| heapify(arr, i, 0) | ||
|
|
||
| return arr | ||
|
|
||
| # | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Чтобы не комментировать такие вещи, оборачивайте то, что должно запускаться только при запуске непосредственно самого файла, в |
||
| # data = [] | ||
| # n = int(input('Введите количество элементов: ')) | ||
| # | ||
| # print(f'Введите {n} элементов') | ||
| # for i in range(n): | ||
| # try: | ||
| # current = int(input()) | ||
| # except ValueError: | ||
| # print("Wrong input!") | ||
| # current = int(input()) | ||
| # | ||
| # data.append(current) | ||
| # | ||
| # heap_sort(data) | ||
| # print(data) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| # Инструкция по использованию тестов | ||
|
|
||
| Домашнее задание 6.1 Heap sort | ||
|
|
||
| 1. Откройте терминал и перейдите в директорию с файлами приложения (hw_6_1_sort_with_test) | ||
| 2. Выполните команду запуска тестов: | ||
| ```console | ||
| pytest test_hw_6_1_sort_with_test.py | ||
| ``` | ||
| 3. Смотрите результат |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| from hw_6_1_sort_with_test import heap_sort | ||
| from random import randint, uniform | ||
| import pytest | ||
|
|
||
| """Обычные тесты""" | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| ["n"], [(([randint(0, 300) for _ in range(10)]),) for _ in range(10)] | ||
| ) | ||
| def test_heap_sort_positive(n): | ||
| """Тест с неотрицательными числами""" | ||
| assert heap_sort(n) == sorted(n) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| ["n"], [(([randint(-300, -1) for _ in range(10)]),) for _ in range(10)] | ||
| ) | ||
| def test_heap_sort_negative(n): | ||
| """Тест с отрицательными числами""" | ||
| assert heap_sort(n) == sorted(n) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| ["n"], [(([uniform(-50, 50) for _ in range(10)]),) for _ in range(10)] | ||
| ) | ||
| def test_float_numbers(n): | ||
| """Тест с числами с плавающей точкой""" | ||
| assert heap_sort(n) == sorted(n) | ||
|
|
||
|
|
||
| """Тесты крайних случаев""" | ||
|
|
||
|
|
||
| def test_empty_list(): | ||
| """Тест пустого списка""" | ||
| assert heap_sort([]) == [] | ||
|
|
||
|
|
||
| def test_single_element(): | ||
| """Тест одного элемента""" | ||
| assert heap_sort([5]) == [5] | ||
|
|
||
|
|
||
| def test_large_random_list(): | ||
| """Тест большого случайного списка""" | ||
| test_list = [randint(-1000, 1000) for _ in range(1000)] | ||
| assert heap_sort(test_list) == sorted(test_list) | ||
|
|
||
|
|
||
| def test_very_large_numbers(): | ||
| """Тест с очень большими числами""" | ||
| assert heap_sort([2 ** 100, 0, -1, -2 ** 11]) == [-2 ** 11, -1, 0, 2 ** 100] | ||
|
|
||
|
|
||
| def test_already_sorted(): | ||
| """Тест уже отсортированного массива""" | ||
| assert heap_sort([1, 2, 3, 4, 5]) == [1, 2, 3, 4, 5] | ||
|
|
||
|
|
||
| def test_duplicates(): | ||
| """Тест с дубликатами""" | ||
| assert heap_sort([3, 1, 4, 1, 5, 9, 2, 6, 5]) == [1, 1, 2, 3, 4, 5, 5, 6, 9] | ||
|
|
||
|
|
||
| """Некоторые сортировки для сравнения""" | ||
|
|
||
|
|
||
| def bubble_sort(arr): | ||
| """Пузырьковая сортировка для сравнения""" | ||
| if not arr: | ||
| return arr.copy() | ||
| result = arr.copy() | ||
| n = len(result) | ||
| for i in range(n): | ||
| for j in range(0, n - i - 1): | ||
| if result[j] > result[j + 1]: | ||
| result[j], result[j + 1] = result[j + 1], result[j] | ||
| return result | ||
|
|
||
|
|
||
| def selection_sort(arr): | ||
| """Сортировка выбором для сравнения""" | ||
| if not arr: | ||
| return arr.copy() | ||
| result = arr.copy() | ||
| n = len(result) | ||
| for i in range(n): | ||
| min_idx = i | ||
| for j in range(i + 1, n): | ||
| if result[j] < result[min_idx]: | ||
| min_idx = j | ||
| result[i], result[min_idx] = result[min_idx], result[i] | ||
| return result | ||
|
|
||
|
|
||
| """Сравнение с другими сортировками""" | ||
|
|
||
|
|
||
| def test_heap_sort_builtin(): | ||
| """Сравнение с встроенной сортировкой""" | ||
| n = [1, 2, 10, 1, 100] | ||
| assert heap_sort(n) == sorted(n) | ||
|
|
||
|
|
||
| def test_compare_with_bubble_sort(): | ||
| """Сравнение с пузырьковой сортировкой""" | ||
| n = [1, 2, 10, 1, 100] | ||
|
|
||
| assert heap_sort(n) == bubble_sort(n) | ||
|
|
||
|
|
||
| def test_compare_with_selection_sort(): | ||
| """Сравнение с сортировкой выбором""" | ||
| n = [1, 2, 10, 1, 100] | ||
| assert heap_sort(n) == selection_sort(n) | ||
|
Comment on lines
+100
to
+116
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Нужно использовать
Comment on lines
+97
to
+116
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Для property based тестов нужно тоже генерировать массивы и сравнивать на них сортировки. |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Нет смысла начинать с
n, эффективнее начинать с последнего родительского узлаn // 2 - 1.