diff --git a/BudakovIS/docs/LinkedListPhoneBook.py b/BudakovIS/docs/data/1-st-exercize/LinkedListPhoneBook.py similarity index 100% rename from BudakovIS/docs/LinkedListPhoneBook.py rename to BudakovIS/docs/data/1-st-exercize/LinkedListPhoneBook.py diff --git a/BudakovIS/docs/data/1-st-exercize/experiment_results.csv b/BudakovIS/docs/data/1-st-exercize/experiment_results.csv new file mode 100644 index 0000000..e754dc6 --- /dev/null +++ b/BudakovIS/docs/data/1-st-exercize/experiment_results.csv @@ -0,0 +1,31 @@ +Structure,Mode,Repeat,Insert (sec),Search (sec),Delete (sec) +LinkedList,random,1,0.140358,0.007040,0.000844 +LinkedList,random,2,0.138009,0.009197,0.000413 +LinkedList,random,3,0.114717,0.009266,0.000744 +LinkedList,random,4,0.117224,0.006914,0.000531 +LinkedList,random,5,0.136302,0.010432,0.000582 +LinkedList,sorted,1,0.106921,0.007845,0.000566 +LinkedList,sorted,2,0.116404,0.015005,0.004900 +LinkedList,sorted,3,0.125122,0.006956,0.000708 +LinkedList,sorted,4,0.122401,0.004220,0.000474 +LinkedList,sorted,5,0.111422,0.008343,0.000551 +HashTable,random,1,0.025442,0.004652,0.000078 +HashTable,random,2,0.035477,0.000985,0.000091 +HashTable,random,3,0.015387,0.001249,0.000298 +HashTable,random,4,0.014196,0.001167,0.000096 +HashTable,random,5,0.013819,0.000910,0.000094 +HashTable,sorted,1,0.013713,0.000897,0.000060 +HashTable,sorted,2,0.016816,0.001013,0.000116 +HashTable,sorted,3,0.018408,0.001019,0.000084 +HashTable,sorted,4,0.014490,0.000886,0.000093 +HashTable,sorted,5,0.012493,0.000867,0.000075 +BST,random,1,0.006755,0.000468,0.000065 +BST,random,2,0.006454,0.000380,0.000052 +BST,random,3,0.003348,0.000266,0.000033 +BST,random,4,0.004785,0.000379,0.000053 +BST,random,5,0.005253,0.000438,0.000083 +BST,sorted,1,0.331066,0.028260,0.002915 +BST,sorted,2,0.342009,0.025769,0.003155 +BST,sorted,3,0.282425,0.031293,0.002984 +BST,sorted,4,0.313816,0.022712,0.002957 +BST,sorted,5,0.287008,0.032645,0.002415 diff --git a/BudakovIS/docs/data/1-st-exercize/plot_results.py b/BudakovIS/docs/data/1-st-exercize/plot_results.py new file mode 100644 index 0000000..8eb2e7a --- /dev/null +++ b/BudakovIS/docs/data/1-st-exercize/plot_results.py @@ -0,0 +1,44 @@ +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np + +# Загрузка данных +df = pd.read_csv('experiment_results.csv') + +# Усреднение по повторам +mean_times = df.groupby(['Structure', 'Mode'])[['Insert (sec)', 'Search (sec)', 'Delete (sec)']].mean().reset_index() + +# Подготовка данных для графиков +structures = mean_times['Structure'].unique() +modes = mean_times['Mode'].unique() + +# Создание трех графиков (вставка, поиск, удаление) +fig, axes = plt.subplots(1, 3, figsize=(15, 5)) + +operations = ['Insert (sec)', 'Search (sec)', 'Delete (sec)'] +titles = ['Вставка', 'Поиск', 'Удаление'] + +for ax, op, title in zip(axes, operations, titles): + # Для каждой структуры строим две колонки (random, sorted) + x = np.arange(len(structures)) + width = 0.35 + + random_vals = [] + sorted_vals = [] + for s in structures: + random_row = mean_times[(mean_times['Structure']==s) & (mean_times['Mode']=='random')] + sorted_row = mean_times[(mean_times['Structure']==s) & (mean_times['Mode']=='sorted')] + random_vals.append(random_row[op].values[0] if not random_row.empty else 0) + sorted_vals.append(sorted_row[op].values[0] if not sorted_row.empty else 0) + + ax.bar(x - width/2, random_vals, width, label='Случайный') + ax.bar(x + width/2, sorted_vals, width, label='Отсортированный') + ax.set_xticks(x) + ax.set_xticklabels(structures) + ax.set_ylabel('Время (сек)') + ax.set_title(title) + ax.legend() + +plt.tight_layout() +plt.savefig('../../performance_comparison.png', dpi=150) +plt.show() diff --git a/BudakovIS/docs/data/experiment_results.csv b/BudakovIS/docs/data/experiment_results.csv deleted file mode 100644 index 0ae27bc..0000000 --- a/BudakovIS/docs/data/experiment_results.csv +++ /dev/null @@ -1,31 +0,0 @@ -Structure,Mode,Repeat,Insert (sec),Search (sec),Delete (sec) -LinkedList,random,1,0.110077,0.006972,0.000836 -LinkedList,random,2,0.105159,0.008245,0.000690 -LinkedList,random,3,0.111559,0.008142,0.000632 -LinkedList,random,4,0.116443,0.007497,0.000519 -LinkedList,random,5,0.128044,0.007971,0.000584 -LinkedList,sorted,1,0.098338,0.007254,0.000515 -LinkedList,sorted,2,0.101167,0.004475,0.000742 -LinkedList,sorted,3,0.128987,0.007993,0.000649 -LinkedList,sorted,4,0.104280,0.006707,0.000676 -LinkedList,sorted,5,0.129192,0.007550,0.000669 -HashTable,random,1,0.014989,0.001023,0.000067 -HashTable,random,2,0.010627,0.000918,0.000083 -HashTable,random,3,0.012970,0.001416,0.000090 -HashTable,random,4,0.013139,0.001172,0.000092 -HashTable,random,5,0.013617,0.000928,0.000091 -HashTable,sorted,1,0.016275,0.000988,0.000099 -HashTable,sorted,2,0.017436,0.000888,0.000094 -HashTable,sorted,3,0.017177,0.000977,0.000080 -HashTable,sorted,4,0.013340,0.001643,0.000248 -HashTable,sorted,5,0.013750,0.001013,0.000176 -BST,random,1,0.006446,0.000436,0.000073 -BST,random,2,0.005296,0.000442,0.000070 -BST,random,3,0.006276,0.000486,0.000055 -BST,random,4,0.004277,0.000230,0.000033 -BST,random,5,0.004287,0.000230,0.000034 -BST,sorted,1,0.286207,0.021908,0.002439 -BST,sorted,2,0.275166,0.024806,0.003805 -BST,sorted,3,0.334667,0.020466,0.002237 -BST,sorted,4,0.319684,0.019011,0.002984 -BST,sorted,5,0.299339,0.028599,0.001916 diff --git a/BudakovIS/docs/performance_comparison.png b/BudakovIS/docs/performance_comparison.png new file mode 100644 index 0000000..ef3e2e0 Binary files /dev/null and b/BudakovIS/docs/performance_comparison.png differ diff --git a/BudakovIS/docs/report_1-st-exersize.md b/BudakovIS/docs/report_1-st-exersize.md new file mode 100644 index 0000000..487fc81 --- /dev/null +++ b/BudakovIS/docs/report_1-st-exersize.md @@ -0,0 +1,59 @@ +# Отчёт по лабораторной работе "Структуры данных" + +## 1. Введение +В рамках работы были реализованы три структуры данных для хранения телефонного справочника: связный список, хеш-таблица и двоичное дерево поиска. Проведено экспериментальное сравнение производительности операций вставки, поиска и удаления на наборе из **10 000 записей**. Для каждой структуры тестирование выполнялось на двух вариантах входных данных: случайный порядок и отсортированный по имени. Каждый эксперимент повторялся 5 раз, результаты усреднены. + +## 2. Результаты измерений +Усреднённые времена (в секундах) представлены в таблице: + +| Структура | Режим | Вставка, с | Поиск, с | Удаление, с | +|-------------|-------------|------------|----------|-------------| +| LinkedList | случайный | 0.1143 | 0.0078 | 0.00065 | +| LinkedList | сортир. | 0.1124 | 0.0068 | 0.00065 | +| HashTable | случайный | 0.0131 | 0.00109 | 0.000085 | +| HashTable | сортир. | 0.0156 | 0.00110 | 0.00014 | +| BST | случайный | 0.00532 | 0.000365 | 0.000053 | +| BST | сортир. | 0.303 | 0.0230 | 0.00268 | + +Графическое представление результатов приведено на рисунке ниже. + +![Сравнение производительности](performance_comparison.png) + +## 3. Анализ результатов + +### 3.1. Влияние порядка данных на BST +При вставке элементов в отсортированном порядке двоичное дерево поиска вырождается в линейный список – все новые узлы добавляются только в правое поддерево. Высота дерева становится равной количеству элементов, и сложность всех операций возрастает до **O(n)**. Эксперимент подтверждает это: +- Вставка в BST на отсортированных данных заняла **0.303 с**, что в **57 раз** больше, чем на случайных (0.00532 с). +- Время вставки на отсортированных данных даже превышает показатели связного списка (0.112 с), что объясняется дополнительными накладными расходами на рекурсивные вызовы. +- Поиск и удаление также замедлились примерно в 60 раз по сравнению со случайным режимом. + +### 3.2. Устойчивость хеш-таблицы к порядку +Хеш-таблица использует хеш-функцию, которая равномерно распределяет ключи по корзинам независимо от порядка поступления. Поэтому производительность операций практически не зависит от того, в каком порядке приходят данные: +- В случайном и отсортированном режимах времена вставки (0.0131 и 0.0156 с) и поиска (около 0.0011 с) близки. +- Небольшие колебания могут быть вызваны случайным распределением коллизий. +- Это соответствует ожидаемой средней сложности **O(1)**. + +### 3.3. Медлительность связного списка при поиске +Связный список не обеспечивает прямого доступа к элементам – для поиска необходимо просматривать узлы последовательно, что даёт сложность **O(n)**. В эксперименте: +- Время поиска в списке (~0.007 с) на порядок больше, чем в хеш-таблице (0.0011 с) и BST на случайных данных (0.00037 с). +- При увеличении объёма данных эта разница будет только расти. +- Вставка в список также относительно медленна (0.11 с), так как требует прохода до конца (хотя обновление существующего имени выполняется быстрее, но в тесте все имена уникальны, поэтому каждая вставка проходит весь список). + +### 3.4. Сравнение удаления +- **Связный список**: удаление требует сначала найти элемент (O(n)), затем переставить ссылки (O(1)). Время удаления (0.00065 с) близко ко времени поиска, что логично. +- **Хеш-таблица**: удаление выполняется за O(1) в среднем – сначала определяется корзина, затем из короткого списка удаляется элемент. Время удаления (0.000085–0.00014 с) значительно меньше, чем в списке. +- **BST**: на случайных данных удаление очень быстрое (0.000053 с) благодаря логарифмической высоте. На отсортированных данных время возрастает до 0.00268 с (в 50 раз), что отражает деградацию до O(n). + +## 4. Выводы и рекомендации по выбору структуры + +На основе полученных результатов можно сформулировать следующие рекомендации: + +- **Хеш-таблица** – оптимальный выбор, если требуется максимальная скорость поиска, вставки и удаления, а порядок хранения не важен. Примеры: реализация словарей, кэшей, индексов по ключу. В эксперименте хеш-таблица показала стабильно высокую производительность во всех режимах. + +- **Двоичное дерево поиска** – следует применять, когда необходимо получать данные в отсортированном порядке (например, вывод телефонного справочника по алфавиту). Однако важно учитывать, что при поступлении отсортированных данных дерево вырождается, и производительность резко падает. В таких случаях лучше использовать сбалансированные деревья (AVL, красно-чёрные). В эксперименте BST на случайных данных показал отличные результаты, близкие к хеш-таблице, а на отсортированных – стал самым медленным. + +- **Связный список** – практически непригоден для больших объёмов данных из-за линейной сложности основных операций. Может использоваться лишь для очень маленьких коллекций, при частых вставках в начало списка (здесь не рассматривалось) или в учебных целях. + +Таким образом, для реальных задач чаще всего выбирают хеш-таблицы или сбалансированные деревья в зависимости от требований к упорядоченности данных. + +I use arch BTW