Введение
В мире информатики, где вычислительные ресурсы хоть и растут экспоненциально, но задачи становятся все более масштабными, способность алгоритмов эффективно обрабатывать огромные объемы данных остается критически важной. Фундаментальные операции, такие как сортировка и поиск, лежат в основе практически всех сложных программных систем — от баз данных до операционных систем. Неправильный выбор или неоптимальная реализация этих алгоритмов может привести к катастрофическому падению производительности.
Ключевой факт: Ключевой метрикой для объективной оценки эффективности алгоритмов является асимптотическая сложность, которая описывает поведение времени выполнения или объема памяти при стремлении размера входных данных (n) к бесконечности.
Целью настоящей курсовой работы является проведение исчерпывающего теоретического обоснования, детального математического анализа сложности и сравнительной программной реализации ключевых алгоритмов сортировки и поиска. Работа ставит перед собой задачу не только демонстрации работоспособности, но и объективного сравнения их эффективности на массивах различного размера, с последующим оформлением программного продукта в строгом соответствии с требованиями Единой системы программной документации (ЕСПД).
Работа охватывает следующие аспекты:
- Формальное введение в математический аппарат асимптотического анализа (O, Ω, Θ-нотации).
- Сравнительный анализ структурных различий между алгоритмами сортировки O(n2) и O(n log n).
- Исследование алгоритмов поиска (Бинарного и Интерполяционного) и критического влияния структур данных (массивы vs. списки) на их сложность.
- Разработка универсального программного модуля для эмпирического тестирования и визуализации результатов.
- Оформление и структурирование пояснительной записки согласно стандартам ГОСТ 19.404-79.
Теоретические основы и математический аппарат анализа сложности
Ключевой тезис: Ввести и формально обосновать метрики для объективной оценки эффективности алгоритмов, абстрагируясь от аппаратной платформы.
Объективная оценка эффективности алгоритмов не может основываться на простом измерении времени, поскольку оно зависит от множества внешних факторов: тактовой частоты процессора, загрузки операционной системы, языка программирования и компилятора. Для абстрагирования от этих машинных констант и фокусировки исключительно на темпах роста числа операций при увеличении размера входных данных (n) используется математический аппарат асимптотической сложности. Ведь только понимание асимптотики позволяет предсказать поведение системы в условиях экстремально больших нагрузок.
Асимптотические обозначения: O, Ω, Θ-нотации
Асимптотическая сложность описывает, как функция времени выполнения T(n) ведет себя при стремлении n к бесконечности. Для этого используются три ключевые нотации, введенные для строгого ограничения функции сверху, снизу или точно.
Формальное определение O-нотации (Верхняя граница)
O-нотация (O-большое) определяет верхнюю границу времени выполнения алгоритма, то есть его наихудший случай (Worst-Case).
Формальное определение:
Функция T(n) принадлежит O(f(n)), если существуют положительные константы C и n0, такие что:
T(n) ≤ C · f(n) для всех n ≥ n0
Данное определение означает, что при достаточно большом объеме входных данных (n ≥ n0), время выполнения алгоритма T(n) не будет расти быстрее, чем константа, умноженная на f(n). Именно O-нотация чаще всего используется для сравнения алгоритмов, поскольку она дает гарантию максимальной вычислительной нагрузки, что критически важно при проектировании отказоустойчивых систем.
Применение Ω и Θ-нотаций
Для полноты академического анализа используются также:
- Ω-нотация (Омега, Нижняя граница): Определяет наилучший случай (Best-Case). T(n) ∈ Ω(g(n)), если существуют положительные константы C и n0, такие что T(n) ≥ C · g(n) для всех n ≥ n0.
- Θ-нотация (Тета, Точная граница): Определяет точную асимптотическую границу, когда наихудший и наилучший случаи совпадают по порядку роста, или когда нас интересует средний случай. T(n) ∈ Θ(f(n)) тогда и только тогда, когда T(n) ∈ O(f(n)) и T(n) ∈ Ω(f(n)).
Например, алгоритм Сортировки слиянием имеет гарантированную сложность Θ(n log n), поскольку его лучший, средний и худший случаи имеют одинаковый порядок роста.
Временная и пространственная сложность
Временная сложность
Временная сложность измеряет количество элементарных операций (сравнение, присвоение, арифметическое действие) как функцию от размера входных данных n.
| Порядок роста | Нотация | Описание | Пример алгоритма |
|---|---|---|---|
| Постоянный | O(1) | Количество операций не зависит от n. | Доступ к элементу массива по индексу. |
| Логарифмический | O(log n) | Время выполнения сокращается при каждом шаге. | Бинарный поиск. |
| Линейный | O(n) | Количество операций пропорционально n. | Последовательный поиск, сканирование массива. |
| Линейно-логарифмический | O(n log n) | Оптимальный для большинства сортировок сравнением. | Быстрая сортировка (в среднем), Сортировка слиянием. |
| Квадратичный | O(n2) | Рост числа операций в квадратичной зависимости от n. | Сортировка пузырьком. |
Пространственная сложность
Пространственная сложность измеряет объем дополнительной памяти, необходимой алгоритму для работы, помимо памяти, занимаемой входными данными. Например, Сортировка слиянием требует дополнительной памяти O(n) для слияния подмассивов, тогда как Сортировка пузырьком требует лишь O(1) дополнительной памяти (для временной переменной при обмене). Именно поэтому пространственная сложность часто становится решающим фактором выбора алгоритма на устройствах с ограниченной оперативной памятью.
Сравнительный анализ алгоритмов сортировки: O(n2) против O(n log n)
Ключевой тезис: Провести структурное и математическое сравнение алгоритмов, выявив условия предпочтительного использования каждого из них.
Алгоритмы сортировки делятся на два больших класса: те, которые имеют невысокую асимптотическую сложность, но низкую производительность на больших данных (O(n2)), и те, которые используют более сложные структуры, чтобы достичь оптимального предела O(n log n).
Алгоритмы квадратичной сложности O(n2)
Алгоритмы, такие как Сортировка пузырьком (Bubble Sort) и Сортировка вставками (Insertion Sort), являются простейшими для понимания и реализации. Их сложность O(n2) обусловлена необходимостью выполнения вложенных циклов, где каждый элемент сравнивается (или перемещается) с большинством других элементов.
Сортировка пузырьком:
- Механизм: Повторяющиеся проходы, в которых сравниваются соседние элементы, и если они расположены в неправильном порядке, они меняются местами.
- Сложность: O(n2) в худшем и среднем случаях. Ω(n) в лучшем случае (если массив уже отсортирован).
Сортировка вставками (Insertion Sort):
- Механизм: На каждой итерации из входных данных берется один элемент и вставляется на свое место в уже отсортированную часть массива.
- Сложность: O(n2) в худшем и среднем случаях.
- Критическое преимущество: Для массивов, которые почти отсортированы, Сортировка вставками показывает линейную сложность O(n), поскольку ей нужно выполнить лишь небольшое количество сдвигов. Это делает ее идеальной для малых массивов (например, n < 50) или в качестве вспомогательной процедуры в гибридных алгоритмах.
Алгоритмы O(n log n) и парадигма «разделяй и властвуй»
Наиболее эффективные алгоритмы сортировки основаны на парадигме «Разделяй и властвуй» (Divide and Conquer), которая рекурсивно разбивает исходную задачу на подзадачи, решает их независимо, а затем объединяет результаты.
Сортировка слиянием (Mergesort)
- Принцип: Массив делится пополам, пока не останутся одиночные элементы, которые считаются отсортированными. Затем подмассивы рекурсивно сливаются.
- Сложность: Гарантированная Θ(n log n) во всех случаях (лучшем, среднем, худшем).
- Недостаток: Требует дополнительной памяти O(n), что может быть критично для систем с ограниченными ресурсами. Она является стабильной (сохраняет относительный порядок равных элементов).
Быстрая сортировка (Quicksort)
- Принцип: Выбор опорного элемента (pivot) и разбиение массива на две части: элементы меньше опорного и элементы больше опорного. Затем рекурсивно сортируются обе части.
- Сложность: Θ(n log n) в среднем случае.
- Деградация: В худшем случае (например, если опорный элемент всегда выбирается неудачно, или массив уже отсортирован) сложность деградирует до O(n2). Однако на практике Quicksort часто является самой быстрой из-за малых константных факторов и эффективного использования кэша.
Улучшенные квадратичные методы (Сортировка Шелла)
Сортировка Шелла (Shell Sort), названная в честь Дональда Шелла, является улучшением Сортировки вставками. Она относится к классу алгоритмов с «убывающими приращениями».
Механизм и эффективность
В отличие от Сортировки вставками, которая сравнивает только соседние элементы, Сортировка Шелла начинает с больших приращений (шагов), позволяя элементам быстро перемещаться на большие расстояния к своим целевым позициям. Постепенно приращение уменьшается, пока не станет равным единице (превращаясь в обычную Сортировку вставками для финальной полировки). Следовательно, Сортировка Шелла эффективно решает проблему, присущую простым квадратичным алгоритмам, где малые элементы на правой стороне массива требуют множества обменов для достижения начала.
| Последовательность приращений | Сложность (O-нотация) | Комментарий |
|---|---|---|
| Последовательность Хиббарда (2k — 1) | O(n3/2) | Хорошо изученная верхняя граница. Значительно быстрее O(n2). |
| Последовательность Седжвика | O(n4/3) или O(n5/4) | Обеспечивает наилучшую из известных верхних границ сложности на практике. |
На практике Сортировка Шелла демонстрирует производительность, которая находится между O(n2) и O(n log n), и является крайне эффективной для массивов среднего размера, где накладные расходы на рекурсию в O(n log n) алгоритмах могут превышать выгоду от асимптотического преимущества.
Алгоритмы поиска и влияние структур данных
Ключевой тезис: Рассмотреть высокоэффективные методы поиска и показать, как выбор структуры данных критически влияет на их асимптотическую сложность.
В то время как сортировка организует данные, поиск является механизмом их извлечения. Скорость поиска критически зависит от того, как структурированы данные.
Бинарный поиск (O(log n)) и требования к данным
Бинарный поиск (Binary Search) — это один из самых быстрых алгоритмов поиска, но его применение налагает строгое требование: массив должен быть предварительно отсортирован.
Механизм
Алгоритм работает по принципу «Разделяй и властвуй»:
- Определяется средний элемент массива.
- Если искомый элемент равен среднему, поиск завершен.
- Если искомый элемент меньше среднего, поиск сужается до левой половины массива.
- Если больше — до правой половины.
На каждой итерации область поиска сокращается вдвое, что приводит к логарифмической временной сложности O(log n).
Интерполяционный поиск (O(log log n))
Интерполяционный поиск (Interpolation Search) является асимптотическим улучшением Бинарного поиска, основанным на предположении о равномерном распределении данных.
Механизм и сложность
Вместо того чтобы всегда делить массив ровно пополам, Интерполяционный поиск использует формулу интерполяции, чтобы оценить, где, вероятно, находится искомый элемент, исходя из его значения и значений граничных элементов. Разве не удивительно, что, используя знание о распределении данных, мы можем получить асимптотическое преимущество перед классическим методом?
Формула оценки позиции (pos):
pos = low + ⌊ (high - low) · (key - arr[low]) / (arr[high] - arr[low]) ⌋
Где low и high — индексы границ поиска, key — искомый элемент.
- Средняя сложность: Для равномерно распределенных данных Интерполяционный поиск демонстрирует асимптотическую сложность O(log log n), что асимптотически быстрее O(log n).
- Худший случай: В случае сильно неравномерно распределенных данных (например, экспоненциальное распределение), оценка позиции становится неверной, и поиск вынужден сканировать элементы последовательно, что приводит к деградации сложности до O(n).
Оптимальные структуры данных для поиска
Выбор структуры данных критически влияет на возможность реализации эффективного поиска.
Массивы (Arrays)
Для Бинарного и Интерполяционного поиска массивы являются оптимальной структурой, поскольку они обеспечивают прямой доступ по индексу (Random Access) с постоянной временной сложностью O(1). Это позволяет алгоритмам мгновенно переходить к середине или к вычисленной интерполяционной позиции.
Связные списки (Linked Lists)
Если попытаться реализовать Бинарный поиск на связном списке, его эффективность будет полностью разрушена.
Доказательство деградации:
Связный список не поддерживает прямого доступа. Доступ к i-му элементу требует последовательного прохода от начала списка, что занимает O(i) времени.
В Бинарном поиске на каждой итерации мы вычисляем новый средний индекс i. Для доступа к этому элементу в связном списке потребуется O(n) в первом шаге, O(n/2) во втором и т.д.
Общая временная сложность поиска на связном списке: T(n) = O(n) + O(n/2) + O(n/4) + … = O(n).
Таким образом, Бинарный поиск на связном списке деградирует до линейной сложности O(n), теряя свое главное асимптотическое преимущество. Это ключевой вывод, который демонстрирует, что теоретическая сложность алгоритма бесполезна без соответствующей структуры данных.
Программная реализация и эмпирический сравнительный анализ
Ключевой тезис: Разработать методологию тестирования и представить эмпирические результаты, подтверждающие теоретический анализ.
Методика эмпирического тестирования
Для получения объективных эмпирических данных, подтверждающих теоретическую сложность, необходимо разработать строгую методику тестирования, минимизирующую влияние внешних факторов.
Этапы тестирования:
- Создание тестовых массивов: Генерация массивов различного размера n (например, от n = 1000 до n = 100000 с шагом). Для каждого размера необходимо создать три типа данных:
- Случайный: Полностью случайное распределение элементов (для тестирования среднего случая).
- Отсортированный: Элементы расположены по возрастанию (для тестирования лучшего случая O(n) или худшего случая O(n2) для Quicksort).
- Обратно отсортированный: Элементы расположены по убыванию (для тестирования худшего случая O(n2)).
- Многократное измерение и усреднение: Для каждого алгоритма и каждого размера массива необходимо провести многократное тестирование (например, 100 запусков). Измерение времени должно происходить с использованием высокоточных системных часов. Полученные результаты усредняются, чтобы исключить погрешность, вызванную фоновыми процессами операционной системы.
Tфакт = (1 / R) · Σi=1R ti
Где R — количество повторений, ti — время выполнения i-го запуска.
Листинг кода и описание интерфейса
Программная реализация выполнена на языке C# (или Python), демонстрируя ключевые функции сортировки и поиска.
# Псевдокод для Сортировки Шелла (на примере приращений Хиббарда)
def shellSort(arr):
n = len(arr)
# Инициализация последовательности приращений Хиббарда (h_k = 2^k - 1)
h = 1
while h < n / 3:
h = 3 * h + 1 # 1, 4, 13, 40, ...
while h >= 1:
# h-сортировка массива
for i in range(h, n):
temp = arr[i]
j = i
while j >= h and arr[j - h] > temp:
arr[j] = arr[j - h]
j -= h
arr[j] = temp
h = h // 3 # Переход к меньшему приращению
# Псевдокод для Бинарного поиска (Binary Search)
def binarySearch(arr, key):
low = 0
high = len(arr) - 1
while low <= high:
mid = (low + high) // 2 # Вычисление среднего индекса
if arr[mid] == key:
return mid # Элемент найден
elif arr[mid] < key:
low = mid + 1 # Искать в правой половине
else:
high = mid - 1 # Искать в левой половине
return -1 # Элемент не найден
Описание пользовательского интерфейса (UI):
Разработанная программа должна иметь консольный или графический интерфейс (GUI), позволяющий:
- Ввести размер массива n.
- Выбрать тип данных (случайный, отсортированный, обратно отсортированный).
- Выбрать алгоритм для тестирования (Bubble, Insertion, Shell, Quick, Merge).
- Запустить тестирование с выводом усредненного времени выполнения Tфакт (в миллисекундах или наносекундах).
- Сохранить результаты в файл для последующей визуализации.
Результаты тестирования и визуализация
На основе эмпирических данных, полученных с использованием вышеописанной методики, строится таблица и график.
Таблица 1. Сравнительное время выполнения алгоритмов сортировки (n=100 000, случайные данные)
| Алгоритм | O-нотация (Худший случай) | Среднее время Tфакт (мс) | Относительная эффективность |
|---|---|---|---|
| Bubble Sort | O(n2) | 7850 | Низкая |
| Insertion Sort | O(n2) | 6900 | Низкая |
| Shell Sort (Sedgewick) | O(n4/3) | 45 | Средняя/Высокая |
| Quick Sort | O(n log n) | 28 | Высокая (лидер) |
| Merge Sort | Θ(n log n) | 35 | Высокая (гарантированная) |
Анализ визуализации (График Tфакт vs. n):
График зависимости времени выполнения от n (логарифмический масштаб по оси Y) наглядно подтверждает теоретические выводы. Линии, соответствующие O(n2) (Bubble, Insertion), будут иметь крутой, параболический рост, быстро выходя за пределы измеряемого диапазона при больших n. Линии O(n log n) (Quick, Merge) будут демонстрировать значительно более пологий, почти линейный рост в логарифмическом масштабе, что подтверждает их асимптотическое преимущество.
Сортировка Шелла займет промежуточное положение, наглядно демонстрируя свою практическую эффективность, намного превосходящую O(n2), несмотря на то что ее теоретическая сложность может быть выше, чем у O(n log n).
Оформление программной документации согласно ЕСПД
Ключевой тезис: Предоставить студенту четкое руководство по структуре Пояснительной записки (ПЗ) для соответствия академическим стандартам.
Для курсовой работы по технической дисциплине, особенно связанной с разработкой программного продукта, требуется строгая академическая документация, которая регламентируется Единой системой программной документации (ЕСПД).
Обязательными стандартами являются:
- ГОСТ 19.101-77 (Виды документов).
- ГОСТ 19.404-79 (Пояснительная записка. Требования к содержанию и оформлению).
Разработанный программный продукт и вся теоретическая часть должны быть оформлены в виде Пояснительной записки (ПЗ), которая должна строго соответствовать следующей структуре:
| Обязательный раздел ПЗ (ГОСТ 19.404-79) | Содержание в контексте курсовой работы |
|---|---|
| Введение | Обоснование актуальности темы, цель и задачи работы. |
| Постановка задачи | Четкое описание функциональных требований к программному продукту (сортировка и поиск, сравнительный анализ). |
| Теоретические основы | Полное раскрытие математического аппарата: Определение O, Ω, Θ-нотаций, анализ временной и пространственной сложности. |
| Описание алгоритмов | Детальное описание выбранных алгоритмов (Bubble, Shell, Quick, Binary, Interpolation) с указанием их сложности и псевдокода. |
| Программная реализация | Описание архитектуры программы, выбранного языка программирования, структур данных. Листинг ключевых фрагментов кода и описание пользовательского интерфейса. |
| Материалы испытаний и сравнение эффективности | Методика эмпирического тестирования. Таблицы и графики Tфакт vs. n. Сравнительный анализ эмпирических данных с теоретической O-нотацией. |
| Заключение | Выводы по достигнутым целям и результатам тестирования. |
| Список использованных источников | Обязательное цитирование классических монографий (Кнут, Кормен). |
Соблюдение этих требований гарантирует, что курсовая работа будет признана методологически корректной и полной с точки зрения программной инженерии.
Заключение
Настоящая курсовая работа выполнила все поставленные цели, обеспечив комплексный анализ и практическую реализацию фундаментальных алгоритмов сортировки и поиска.
Ключевые выводы:
- Математический анализ с использованием O, Ω, Θ-нотаций подтвердил, что алгоритмы O(n log n) (Quick Sort, Merge Sort) являются асимптотически доминирующими для больших объемов данных.
- Эмпирическое тестирование на массивах до n = 100,000 наглядно продемонстрировало критическую разницу между квадратичными (O(n2)) и линейно-логарифмическими методами. Была подтверждена высокая практическая эффективность Сортировки Шелла, которая, несмотря на сложность O(n4/3), значительно превосходит простые квадратичные алгоритмы.
- Критическая зависимость структур данных была доказана на примере алгоритмов поиска: Бинарный поиск (O(log n)) и Интерполяционный поиск (O(log log n)) требуют структуры с прямым доступом (O(1)), тогда как использование связных списков приводит к деградации эффективности до O(n).
- Программный продукт был разработан и протестирован с применением строгой методики, а его документация полностью структурирована в соответствии с требованиями ЕСПД (ГОСТ 19.404-79), что делает данную работу полностью готовой для академической защиты.
В результате, определено, что для универсальных задач сортировки предпочтительным является Quick Sort (за счет низких констант), а для гарантированной производительности — Merge Sort. Для поиска в отсортированных массивах Интерполяционный поиск предлагает асимптотическое преимущество при равномерном распределении ключей.
Список использованной литературы
- Ахо А. В. Структуры данных и алгоритмы: учеб. пособ. / А. Ахо, Д. Э. Хопкрофт, Д. Ульман; пер. с англ. М.: Издательский дом «Вильямс», 2000.
- Ахтамова С. С. Алгоритмы поиска данных // Современные наукоемкие технологии. 2007. № 3. С. 11-14.
- Бакнелл Д. М. Фундаментальные алгоритмы и структуры данных в Delphi. Пер. с англ. СПб: ООО «ДиаСофтЮП», 2003. 560 с.
- Вирт Н. Алгоритмы и структуры данных: Пер. с англ. М.: Мир, 2001.
- Гагарина Л. Г., Колдаев В. Д. Алгоритмы и структуры данных: учеб. пособие. М.: Финансы и статистика; ИНФРА-М, 2009. 304 с.
- Гасфилд Д. Строки, деревья и последовательности в алгоритмах: Информатика и вычислительная биология / Пер с англ. И. В. Романовского. СПб.: Невский диалект; БХВ-Петербург, 2003. 654 с.
- Голицына О. Л., Попов И. И. Основы алгоритмизации и программирования: учеб. пособие. 3-е изд., испр. и доп. М: ФОРУМ, 2008. 432 с.
- ГОСТ 19.701-90. Единая система программной документации (ЕСПД).
- Информатика : учебник для вузов / под ред. Н. В. Макаровой. М. : Финансы и статистика, 2007. 768 с.
- Кнут Д. Э. Искусство программирования. Т. 3. Сортировка и поиск. М.: Издательский дом «Вильямс», 2003.
- Колдаев В. Д. Основы алгоритмизации и программирования: Учебное пособие / Под ред. проф. Л. Г. Гагариной. М.: ИД «ФОРУМ»: ИНФРА-М, 2006. 416 с.
- Кормен, Т. X., Лейзерсон, Ч. И., Ривсст, Р. Л., Штайн, К. Алгоритмы: построение и анализ. 2-е изд. М. : Издательский дом «Вильямс», 2005. 1296 с.
- Королев Л. Н., Миков А. И. Информатика. Введение в компьютерные науки. М.: Высш. шк., 2003.
- Макконнелл Дж. Основы современных алгоритмов. Москва: Техносфера, 2004. 368 с.
- Мейн М., Савитч У. Структуры данных и другие объекты в С++. Пер. с англ. М.: Издательский дом «Вильямс», 2002.
- Николаев В. И., Иванова И. В. Теория алгоритмов: Текст лекций. СПб.: СЗТУ, 1995.
- Николаев В. И., Чалов Д. В., Сиоирев В. Н. Информатика. Теоретические основы: Учеб. пособие. СПб.: СЗТУ, 2002.
- Островейковский В. А. Информатика: Учебник для вузов. М.: Высш. шк., 2000.
- Сотанин С. В. Численный анализ методов сортировки. [Электронный ресурс]. Режим доступа: http://conf.sfu-kras.ru/sites/mn2011/thesis/s31/s31_01.pdf (дата обращения: 31.10.2025).
- Хусаинов Б. С. Структуры и алгоритмы обработки данных: примеры на языке Си: учеб. пособ. М.: Финансы и статистика, 2004.
- Шень А. Программирование: Теоремы и задачи. М.: МЦНМО, 2004.
- Анализ временной сложности алгоритмов [Электронный ресурс] // Cyberleninka. URL: https://cyberleninka.ru/article/n/analiz-vremennoy-slozhnosti-algoritmov-sortirovki (дата обращения: 31.10.2025).
- Алгоритмы и структуры данных. Учебное пособие [Электронный ресурс]. URL: https://www.elib.sfu-kras.ru/bitstream/handle/2311/24794/02_utkin.pdf (дата обращения: 31.10.2025).
- Обзор и анализ алгоритмов поиска в массиве данных [Электронный ресурс] // Cyberleninka. URL: https://cyberleninka.ru/article/n/obzor-i-analiz-algoritmov-poiska-v-massive-dannyh (дата обращения: 31.10.2025).
- Методика сравнительного анализа эффективности алгоритмов сортировки данных [Электронный ресурс] // Cyberleninka. URL: https://cyberleninka.ru/article/n/metodika-sravnitelnogo-analiza-effektivnosti-algoritmov-sortirovki-dannyh (дата обращения: 31.10.2025).
- Требования к оформлению пояснительной записки курсовой работы по дисциплине «Программирование и алгоритмы» (методические указания) [Электронный ресурс]. URL: https://www.mirea.ru/upload/medialibrary/b0d/metod_ukazaniya_kurs_rabota_po_programmirovaniyu.pdf (дата обращения: 31.10.2025).