2026-rff_mp/ProninVV/aufgabe-1-data-structures/report/document.tex

137 lines
11 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\input{preambule.tex}
\begin{document}
% --- ТИТУЛЬНЫЙ ЛИСТ (упрощенно) ---
\begin{titlepage}
\centering
МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РФ \\
«Национальный исследовательский Нижегородский государственный университет им. Н.И. Лобачевского» \\
\vspace{4cm}
\Large ОТЧЕТ К ЛАБОРАТОРНОЙ РАБОТЕ \\
\vspace{1cm}
\large «Реализация и экспериментальное сравнение базовых структур данных на примере телефонного справочника» \\
\vspace{4cm}
\flushright
Выполнил: студент В. В. Пронин \\
Преподаватель: Н. С. Морозов \\
\vfill
Нижний Новгород \\
2024
\end{titlepage}
\newpage
\tableofcontents
\newpage
\section{Введение}
Эффективность программных систем во многом определяется выбором способов организации данных в оперативной памяти. Задача разработки телефонного справочника является классическим примером, требующим баланса между скоростью вставки новых записей, поиском по ключу и эффективным удалением.
В рамках данной работы исследуются три фундаментальные структуры данных, реализованные «с нуля» в процедурной парадигме программирования на языке Python:
\begin{itemize}
\item \textbf{Связный список (Linked List)} --- динамическая структура, позволяющая оценить базовые механизмы управления указателями и демонстрирующая линейную сложность операций $O(n)$.
\item \textbf{Хеш-таблица (Hash Table)} --- ассоциативный массив, использующий хеширование для обеспечения прямого доступа к данным. Реализация позволяет изучить методы разрешения коллизий и преимущества константной сложности $O(1)$.
\item \textbf{Двоичное дерево поиска (BST)} --- иерархическая структура, обеспечивающая логарифмическую скорость доступа $O(\log n)$ и поддерживающая упорядоченность данных «из коробки».
\end{itemize}
\textbf{Цель работы:} Изучить внутренние алгоритмы работы перечисленных структур, реализовать их без использования встроенных высокоуровневых контейнеров и экспериментально подтвердить теоретические оценки временной сложности на случайных и отсортированных наборах данных.
\section{Реализация структур данных}
\subsection{Связный список}
% Здесь опишите логику ll_insert, ll_find и ll_delete
\subsection{Хеш-таблица}
% Опишите хеш-функцию и метод цепочек
\subsection{Двоичное дерево поиска}
% Опишите рекурсивные алгоритмы и проблему деградации
\section{Методика эксперимента}
Замеры производились для наборов данных объемом $N=500, 1000, 2000, 5000, 10000$ элементов. Использовались два сценария: перемешанные (\textit{shuffled}) и отсортированные по алфавиту (\textit{sorted}) записи. Каждая операция выполнялась 5 раз с последующим вычислением среднего арифметического значения с помощью функции \texttt{time.perf\_counter()}.
\section{Результаты и анализ}
Было проведено серию опытов для $N$ от 500 до 10000.
\subsection*{1. Бинарное дерево поиска (BST) и влияние порядка}
\begin{figure}[H]
\centering
\includegraphics[scale=0.7]{plots/TTree1.eps}
\caption{Зависимость времени выполнения операций в BST от объема данных}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[scale=0.7]{plots/TTree2.eps}
\end{figure}
\begin{itemize}
\item \textbf{Деградация на отсортированных данных:} При вставке отсортированных данных время увеличилось с \textbf{0.124с} ($N=1000$) до \textbf{13.27с} ($N=10000$). Рост времени в 100 раз при увеличении объема данных в 10 раз четко указывает на квадратичную сложность $O(n^2)$ для процесса заполнения всей структуры. Дерево выродилось в линейный список, и поиск места вставки стал занимать $O(n)$ вместо ожидаемого $O(\log n)$.
\item \textbf{Эффективность на перемешанных данных:} На \texttt{shuffled} данных вставка 10000 элементов заняла всего \textbf{0.031с}. Это подтверждает логарифмическую сложность $O(\log n)$ для операций в дереве при случайном распределении ключей.
\end{itemize}
\subsection*{2. Хеш-таблица: Стабильность и скорость}
\begin{figure}[H]
\centering
\includegraphics[scale=0.7]{plots/Thasht1.eps}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[scale=0.7]{plots/Thasht2.eps}
\end{figure}
\begin{itemize}
\item \textbf{Чувствительность к порядку:} Хеш-таблица показала идентичные результаты как на \texttt{shuffled}, так и на \texttt{sorted} данных (около \textbf{0.165с} -- \textbf{0.167с} для 10000 вставок). Это объясняется тем, что хеш-функция распределяет ключи по бакетам независимо от их исходного порядка, предотвращая деградацию структуры.
\item \textbf{Превосходство:} На больших объемах хеш-таблица оказалась самой быстрой структурой для поиска и удаления ($\approx 0.001$с при $N=10000$), что подтверждает теоретическую среднюю сложность $O(1)$.
\item \textbf{Замечание:} Так как реализация использует списки для разрешения коллизий со вставкой в конец, при заполнении таблицы наблюдается рост времени вставки, стремящийся к квадратичному, однако абсолютные значения остаются на порядки ниже, чем у выродившегося BST.
\end{itemize}
\subsection*{3. Связный список: Линейная зависимость}
\begin{figure}[H]
\centering
\includegraphics[scale=0.7]{plots/Tlinklist1.eps}
\end{figure}
\begin{figure}[H]
\centering
\includegraphics[scale=0.7]{plots/Tlinklist2.eps}
\end{figure}
\begin{itemize}
\item \textbf{Поиск и удаление:} Связный список показал худшие результаты среди всех структур на случайных данных. Время поиска при 10000 элементах (\textbf{0.029с}) значительно медленнее, чем у BST на перемешанных данных (\textbf{0.0002с}). Это подтверждает линейную сложность $O(n)$.
\item \textbf{Вставка:} Вставка (вероятно, в конец или с сохранением порядка) дает $O(n^2)$ при заполнении (\textbf{2.83с} -- \textbf{3.00с} на 10000 эл.). Характер роста времени при переходе от $N=5000$ (\textbf{0.71с}) к $N=10000$ подтверждает квадратичную зависимость.
\end{itemize}
\subsection*{Вывод: выбор структуры данных}
\begin{enumerate}
\item \textbf{Хеш-таблица} — наиболее универсальный выбор. Она обеспечивает стабильное $O(1)$ для поиска и не зависит от порядка входящих данных.
\item \textbf{BST} — крайне эффективен ($O(\log n)$) при случайном распределении данных, но без механизмов самобалансировки критически уязвим к отсортированным входным последовательностям, замедляясь до уровня списка.
\item \textbf{Связный список} — продемонстрировал самую низкую производительность на операциях поиска и массовой вставки. Его использование оправдано только в специфических сценариях (например, реализация стека), где работа ведется исключительно с головой списка за $O(1)$.
\end{enumerate}
\subsection*{Сводная таблица результатов}
\begin{table}[H]
\centering
\small
\begin{tabular}{|l|l|c|c|c|c|c|}
\hline
\textbf{Структура} & \textbf{Режим} & \textbf{Опер.} & \textbf{N=500} & \textbf{N=1000} & \textbf{N=5000} & \textbf{N=10000} \\ \hline
\multirow{3}{*}{LinkList} & Shuffled & Insert & 0.0066 & 0.0292 & 0.7089 & 2.8358 \\
& Shuffled & Find & 0.0012 & 0.0026 & 0.0147 & 0.0289 \\
& Sorted & Insert & 0.0065 & 0.0290 & 0.7637 & 3.0042 \\ \hline
\multirow{3}{*}{HashTable} & Shuffled & Insert & 0.0007 & 0.0022 & 0.0468 & 0.1670 \\
& Shuffled & Find & 0.0001 & 0.0002 & 0.0008 & 0.0014 \\
& Sorted & Insert & 0.0007 & 0.0022 & 0.0448 & 0.1646 \\ \hline
\multirow{3}{*}{BinTree} & Shuffled & Insert & 0.0009 & 0.0021 & 0.0145 & 0.0309 \\
& Shuffled & Find & 0.0001 & 0.0001 & 0.0002 & 0.0002 \\
& Sorted & Insert & \textbf{0.0298} & \textbf{0.1239} & \textbf{3.3052} & \textbf{13.2706} \\ \hline
\end{tabular}
\caption{Сравнение минимального времени выполнения операций (в секундах) в зависимости от объема данных $N$}
\end{table}
\end{document}