From dc307573694b53956530cb1ca1bf844b64394ec7 Mon Sep 17 00:00:00 2001 From: ialina07 Date: Fri, 7 Nov 2025 17:33:53 +0000 Subject: [PATCH 1/8] added sorting algorithms --- src/sorting_algorithms/__init__.py | 6 ++++ src/sorting_algorithms/bubble_sort.py | 9 ++++++ src/sorting_algorithms/heap_sort.py | 38 +++++++++++++++++++++++ src/sorting_algorithms/merge_sort.py | 44 +++++++++++++++++++++++++++ src/sorting_algorithms/quick_sort.py | 36 ++++++++++++++++++++++ 5 files changed, 133 insertions(+) create mode 100644 src/sorting_algorithms/__init__.py create mode 100644 src/sorting_algorithms/bubble_sort.py create mode 100644 src/sorting_algorithms/heap_sort.py create mode 100644 src/sorting_algorithms/merge_sort.py create mode 100644 src/sorting_algorithms/quick_sort.py diff --git a/src/sorting_algorithms/__init__.py b/src/sorting_algorithms/__init__.py new file mode 100644 index 0000000..ede1d06 --- /dev/null +++ b/src/sorting_algorithms/__init__.py @@ -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'] diff --git a/src/sorting_algorithms/bubble_sort.py b/src/sorting_algorithms/bubble_sort.py new file mode 100644 index 0000000..968bb51 --- /dev/null +++ b/src/sorting_algorithms/bubble_sort.py @@ -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 + diff --git a/src/sorting_algorithms/heap_sort.py b/src/sorting_algorithms/heap_sort.py new file mode 100644 index 0000000..f58fe13 --- /dev/null +++ b/src/sorting_algorithms/heap_sort.py @@ -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) # Просеиваем дальше diff --git a/src/sorting_algorithms/merge_sort.py b/src/sorting_algorithms/merge_sort.py new file mode 100644 index 0000000..f860aaa --- /dev/null +++ b/src/sorting_algorithms/merge_sort.py @@ -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 diff --git a/src/sorting_algorithms/quick_sort.py b/src/sorting_algorithms/quick_sort.py new file mode 100644 index 0000000..bf4a175 --- /dev/null +++ b/src/sorting_algorithms/quick_sort.py @@ -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 From c886d5349502b518b5d99139d1b7430358744f24 Mon Sep 17 00:00:00 2001 From: ialina07 Date: Fri, 7 Nov 2025 17:35:48 +0000 Subject: [PATCH 2/8] added tests for sorting algorithms --- tests/__init__.py | 0 tests/test_bubble_sort.py | 22 ++++++++++++++++++++++ tests/test_heap_sort.py | 23 +++++++++++++++++++++++ tests/test_merge_sort.py | 23 +++++++++++++++++++++++ tests/test_quick_sort.py | 23 +++++++++++++++++++++++ 5 files changed, 91 insertions(+) create mode 100644 tests/__init__.py create mode 100644 tests/test_bubble_sort.py create mode 100644 tests/test_heap_sort.py create mode 100644 tests/test_merge_sort.py create mode 100644 tests/test_quick_sort.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_bubble_sort.py b/tests/test_bubble_sort.py new file mode 100644 index 0000000..9f1cac0 --- /dev/null +++ b/tests/test_bubble_sort.py @@ -0,0 +1,22 @@ +from 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] diff --git a/tests/test_heap_sort.py b/tests/test_heap_sort.py new file mode 100644 index 0000000..2eab21c --- /dev/null +++ b/tests/test_heap_sort.py @@ -0,0 +1,23 @@ +from 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] + diff --git a/tests/test_merge_sort.py b/tests/test_merge_sort.py new file mode 100644 index 0000000..1ea2f1e --- /dev/null +++ b/tests/test_merge_sort.py @@ -0,0 +1,23 @@ +from 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] + diff --git a/tests/test_quick_sort.py b/tests/test_quick_sort.py new file mode 100644 index 0000000..51d6cec --- /dev/null +++ b/tests/test_quick_sort.py @@ -0,0 +1,23 @@ +from 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] + From b52f5c662bfbf125c98b5cb907a0905e1f29a53e Mon Sep 17 00:00:00 2001 From: ialina07 Date: Wed, 12 Nov 2025 17:51:33 +0300 Subject: [PATCH 3/8] Update python-tests.yml --- .github/workflows/python-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index 65f270e..ab9b9ec 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.7, 3.8, 3.9, 3.10] + python-version: [3.9, 3.10] steps: - uses: actions/checkout@v2 From 0420d4805bc1921cc7ca44b7dfbf4f187b59539d Mon Sep 17 00:00:00 2001 From: ialina07 Date: Wed, 12 Nov 2025 17:57:31 +0300 Subject: [PATCH 4/8] Update python-tests.yml --- .github/workflows/python-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml index b02f561..540c14c 100644 --- a/.github/workflows/python-tests.yml +++ b/.github/workflows/python-tests.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.9, 3.10] + python-version: [3.9, 3.11, 3.12] steps: From 73135945c20f5d0cc3414a033a72164db2a93721 Mon Sep 17 00:00:00 2001 From: ialina07 Date: Wed, 12 Nov 2025 18:02:40 +0300 Subject: [PATCH 5/8] Update test_bubble_sort.py --- tests/test_bubble_sort.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_bubble_sort.py b/tests/test_bubble_sort.py index 9f1cac0..c5767e6 100644 --- a/tests/test_bubble_sort.py +++ b/tests/test_bubble_sort.py @@ -1,4 +1,4 @@ -from sorting_algorithms import bubble_sort +from src.sorting_algorithms import bubble_sort def test_empty_list(): assert bubble_sort([]) == [] From 9e943c431a050f8b799e68c6c99fa41950218dfb Mon Sep 17 00:00:00 2001 From: ialina07 Date: Wed, 12 Nov 2025 18:03:42 +0300 Subject: [PATCH 6/8] Update test_heap_sort.py --- tests/test_heap_sort.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_heap_sort.py b/tests/test_heap_sort.py index 2eab21c..db28347 100644 --- a/tests/test_heap_sort.py +++ b/tests/test_heap_sort.py @@ -1,4 +1,4 @@ -from sorting_algorithms import heap_sort +from src.sorting_algorithms import heap_sort def test_empty_list(): assert heap_sort([]) == [] From 4b284285249cdb17ff4e171390279e5806a13ca6 Mon Sep 17 00:00:00 2001 From: ialina07 Date: Wed, 12 Nov 2025 18:04:20 +0300 Subject: [PATCH 7/8] Update test_merge_sort.py --- tests/test_merge_sort.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_merge_sort.py b/tests/test_merge_sort.py index 1ea2f1e..c09fa2d 100644 --- a/tests/test_merge_sort.py +++ b/tests/test_merge_sort.py @@ -1,4 +1,4 @@ -from sorting_algorithms import merge_sort +from src.sorting_algorithms import merge_sort def test_empty_list(): assert merge_sort([]) == [] From 9d639e0987a76d9285a8408011c21ff2fdf41bd4 Mon Sep 17 00:00:00 2001 From: ialina07 Date: Wed, 12 Nov 2025 18:04:50 +0300 Subject: [PATCH 8/8] Update test_quick_sort.py --- tests/test_quick_sort.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_quick_sort.py b/tests/test_quick_sort.py index 51d6cec..36d72b8 100644 --- a/tests/test_quick_sort.py +++ b/tests/test_quick_sort.py @@ -1,4 +1,4 @@ -from sorting_algorithms import quick_sort +from src.sorting_algorithms import quick_sort def test_empty_list(): assert quick_sort([]) == []