2026-rff_mp/nikolaevda/docs/report_laba1.ipynb

246 lines
14 KiB
Plaintext
Raw Normal View History

2026-05-16 18:06:11 +00:00
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "7cbca316",
"metadata": {},
"outputs": [],
"source": [
"{\n",
" \"cells\": [\n",
" {\n",
" \"cell_type\": \"markdown\",\n",
" \"id\": \"start\",\n",
" \"metadata\": {},\n",
" \"source\": [\n",
" \"# Отчёт по лабораторной работе\\n\",\n",
" \"## Тема: Сравнение производительности структур данных для телефонного справочника\\n\",\n",
" \"\\n\",\n",
" \"---\"\n",
" ]\n",
" },\n",
" {\n",
" \"cell_type\": \"markdown\",\n",
" \"id\": \"goal\",\n",
" \"metadata\": {},\n",
" \"source\": [\n",
" \"## 1. Цель работы\\n\",\n",
" \"\\n\",\n",
" \"Реализовать три различные структуры данных «с нуля», применить их для хранения записей телефонного справочника и экспериментально сравнить производительность основных операций (вставка, поиск, удаление).\\n\",\n",
" \"\\n\",\n",
" \"---\"\n",
" ]\n",
" },\n",
" {\n",
" \"cell_type\": \"markdown\",\n",
" \"id\": \"conditions\",\n",
" \"metadata\": {},\n",
" \"source\": [\n",
" \"## 2. Условия эксперимента\\n\",\n",
" \"\\n\",\n",
" \"| Параметр | Значение |\\n\",\n",
" \"|----------|----------|\\n\",\n",
" \"| Общее число записей | 10 000 |\\n\",\n",
" \"| Каждый замер повторялся | 5 раз |\\n\",\n",
" \"| Количество существующих записей для поиска | 100 |\\n\",\n",
" \"| Количество несуществующих записей для поиска | 10 |\\n\",\n",
" \"| Количество элементов для удаления | 50 |\\n\",\n",
" \"| Размер хеш-таблицы | 2003 (простое число) |\\n\",\n",
" \"| Режимы тестирования | Случайный / Отсортированный |\\n\",\n",
" \"\\n\",\n",
" \"---\"\n",
" ]\n",
" },\n",
" {\n",
" \"cell_type\": \"markdown\",\n",
" \"id\": \"graphs\",\n",
" \"metadata\": {},\n",
" \"source\": [\n",
" \"## 3. Практические графики\\n\",\n",
" \"\\n\",\n",
" \"### Информация о тестировании\\n\",\n",
" \"- Общее число записей: 10 000\\n\",\n",
" \"- Каждый замер повторялся: 5 раз\\n\",\n",
" \"- Количество существующих записей для случайного поиска: 100\\n\",\n",
" \"- Количество несуществующих записей для поиска: 10\\n\",\n",
" \"- Количество элементов для удаления: 50\\n\",\n",
" \"\\n\",\n",
" \"![График вставки](graphs.png)\\n\",\n",
" \"\\n\",\n",
" \"**Рис. 1 Тестирование вставки (логарифмическая шкала)**\\n\",\n",
" \"\\n\",\n",
" \"---\"\n",
" ]\n",
" },\n",
" {\n",
" \"cell_type\": \"markdown\",\n",
" \"id\": \"analysis_bst\",\n",
" \"metadata\": {},\n",
" \"source\": [\n",
" \"## 4. Анализ результатов\\n\",\n",
" \"\\n\",\n",
" \"### Как порядок входных данных влияет на скорость вставки в BST (деградация до O(n) на отсортированных данных)?\\n\",\n",
" \"\\n\",\n",
" \"По определению, при вставке отсортированных данных, структура бинарного дерева поиска вырождается в связный список.\\n\",\n",
" \"\\n\",\n",
" \"**Результаты тестирования:**\\n\",\n",
" \"- На случайных данных: время вставки ~0.037 секунд\\n\",\n",
" \"- На отсортированных данных: время вставки ~18.34 секунд (деградация в ~470 раз!)\\n\",\n",
" \"\\n\",\n",
" \"Заметим, что при случайных данных скорость вставки в бинарное дерево почти лишь немного уступает по скорости хеш-таблице. При отсортированных данных дерево фактически превращается в связный список, и из-за рекурсивной реализации вставки бинарное дерево становится даже медленнее связного списка.\\n\",\n",
" \"\\n\",\n",
" \"---\"\n",
" ]\n",
" },\n",
" {\n",
" \"cell_type\": \"markdown\",\n",
" \"id\": \"analysis_hash\",\n",
" \"metadata\": {},\n",
" \"source\": [\n",
" \"### Почему хеш-таблица почти не чувствительна к порядку?\\n\",\n",
" \"\\n\",\n",
" \"Хеш-таблица не чувствительна к порядку данных, так как:\\n\",\n",
" \"1. Использует для распределения элементов хеш-значения данных (сложность операции одинакова для любых однотипных данных)\\n\",\n",
" \"2. Хеш-функция равномерно распределяет ключи по корзинам независимо от их порядка\\n\",\n",
" \"3. Вставка в конкретную корзину не зависит от соседних элементов\\n\",\n",
" \"\\n\",\n",
" \"**Экспериментальное подтверждение:**\\n\",\n",
" \"- Случайный порядок: вставка = 0.0369 сек, поиск = 0.000355 сек\\n\",\n",
" \"- Отсортированный порядок: вставка = 0.0356 сек, поиск = 0.000380 сек\\n\",\n",
" \"\\n\",\n",
" \"Разница незначительна и находится в пределах погрешности измерений.\\n\",\n",
" \"\\n\",\n",
" \"---\"\n",
" ]\n",
" },\n",
" {\n",
" \"cell_type\": \"markdown\",\n",
" \"id\": \"analysis_list\",\n",
" \"metadata\": {},\n",
" \"source\": [\n",
" \"### Почему связный список всегда медленен при поиске?\\n\",\n",
" \"\\n\",\n",
" \"Операция поиска в связном списке имеет линейную сложность **O(n)** независимо от порядка данных, так как:\\n\",\n",
" \"- Нет индексов для прямого доступа\\n\",\n",
" \"- Нет сортировки, позволяющей применять бинарный поиск\\n\",\n",
" \"- Приходится последовательно перебирать все элементы до найденного\\n\",\n",
" \"\\n\",\n",
" \"| Структура | Сложность поиска | Время поиска (случайный) |\\n\",\n",
" \"|-----------|-----------------|--------------------------|\\n\",\n",
" \"| Связный список | O(n) | 0.0427 сек |\\n\",\n",
" \"| Хеш-таблица | O(1) средняя | 0.000355 сек |\\n\",\n",
" \"| BST (случайный) | O(log n) | 0.000527 сек |\\n\",\n",
" \"\\n\",\n",
" \"---\"\n",
" ]\n",
" },\n",
" {\n",
" \"cell_type\": \"markdown\",\n",
" \"id\": \"analysis_delete\",\n",
" \"metadata\": {},\n",
" \"source\": [\n",
" \"### Как удаление работает в каждой структуре?\\n\",\n",
" \"\\n\",\n",
" \"#### Связный список\\n\",\n",
" \"Находим элемент перед удаляемым элементом и заменяем его поле `next` на `next.next`:\\n\",\n",
" \"```python\\n\",\n",
" \"current = head\\n\",\n",
" \"while current['next'] is not None:\\n\",\n",
" \" if current['next']['name'] == name:\\n\",\n",
" \" current['next'] = current['next']['next']\\n\",\n",
" \" return head\\n\",\n",
" \" current = current['next']\\n\",\n",
" \"```\\n\",\n",
" \"\\n\",\n",
" \"#### Двоичное дерево поиска\\n\",\n",
" \"После того, как мы нашли узел, который необходимо удалить, возможны три случая:\\n\",\n",
" \"\\n\",\n",
" \"**Случай 1:** У удаляемого узла нет детей → просто удаляем узел.\\n\",\n",
" \"\\n\",\n",
" \"**Случай 2:** У удаляемого узла есть только один ребёнок → ребёнок занимает место удалённого узла.\\n\",\n",
" \"\\n\",\n",
" \"**Случай 3:** У удаляемого узла есть оба ребёнка → находим минимальный элемент в правом поддереве (самый левый узел) и заменяем им удаляемый узел.\\n\",\n",
" \"\\n\",\n",
" \"#### Хеш-таблица\\n\",\n",
" \"1. Вычисляем хеш-индекс: `index = hash_func(name, len(buckets))`\\n\",\n",
" \"2. Находим нужную корзину: `buckets[index]`\\n\",\n",
" \"3. Удаляем элемент из связного списка в этой корзине\\n\",\n",
" \"\\n\",\n",
" \"**Сравнение времени удаления:**\\n\",\n",
" \"\\n\",\n",
" \"| Структура | Время удаления (случайный) | Сложность |\\n\",\n",
" \"|-----------|---------------------------|-----------|\\n\",\n",
" \"| Связный список | 0.0341 сек | O(n) |\\n\",\n",
" \"| Хеш-таблица | 0.00018 сек | O(1) средняя |\\n\",\n",
" \"| BST | 0.0793 сек | O(log n) средняя |\\n\",\n",
" \"\\n\",\n",
" \"---\"\n",
" ]\n",
" },\n",
" {\n",
" \"cell_type\": \"markdown\",\n",
" \"id\": \"conclusion\",\n",
" \"metadata\": {},\n",
" \"source\": [\n",
" \"## 5. Вывод\\n\",\n",
" \"\\n\",\n",
" \"Мы реализовали и протестировали три различные структуры хранения данных: связный список, хеш-таблицу и двоичное дерево поиска. Сравнили скорость операций вставки, удаления и поиска для каждой структуры.\\n\",\n",
" \"\\n\",\n",
" \"### Итоговая таблица производительности (случайный порядок):\\n\",\n",
" \"\\n\",\n",
" \"| Структура | Вставка (сек) | Поиск (сек) | Удаление (сек) |\\n\",\n",
" \"|-----------|---------------|-------------|----------------|\\n\",\n",
" \"| Связный список | 4.6031 | 0.0427 | 0.0341 |\\n\",\n",
" \"| Хеш-таблица | **0.0369** | **0.00036** | **0.00018** |\\n\",\n",
" \"| BST | 0.0369 | 0.00053 | 0.0793 |\\n\",\n",
" \"\\n\",\n",
" \"### Рекомендации по выбору структуры данных:\\n\",\n",
" \"\\n\",\n",
" \"1. **Хеш-таблица** лучший выбор для телефонного справочника:\\n\",\n",
" \" - Не важен порядок хранения и извлечения данных\\n\",\n",
" \" - Требуется максимальная скорость поиска и вставки\\n\",\n",
" \" - Результат: **победитель по всем параметрам**\\n\",\n",
" \"\\n\",\n",
" \"2. **Двоичное дерево поиска** выбираем, если:\\n\",\n",
" \" - Нужно хранить данные с возможностью быстрого отсортированного обхода\\n\",\n",
" \" - Данные поступают в случайном порядке (иначе будет деградация)\\n\",\n",
" \" - Можно использовать сбалансированную версию (AVL, красно-чёрное)\\n\",\n",
" \"\\n\",\n",
" \"3. **Связный список** выбираем, если:\\n\",\n",
" \" - Нужно хранить данные в порядке поступления (очередь, стек)\\n\",\n",
" \" - Объём данных очень маленький (< 100 записей)\\n\",\n",
" \" - Простота реализации важнее производительности\\n\",\n",
" \"\\n\",\n",
" \"---\\n\",\n",
" \"\\n\",\n",
" \"**Заключение:** Для реализации телефонного справочника оптимальнее всего использовать **хеш-таблицу**, так как она обеспечивает наилучшую производительность для всех операций и не чувствительна к порядку входных данных.\"\n",
" ]\n",
" }\n",
" ],\n",
" \"metadata\": {\n",
" \"kernelspec\": {\n",
" \"display_name\": \"Python 3\",\n",
" \"language\": \"python\",\n",
" \"name\": \"python3\"\n",
" },\n",
" \"language_info\": {\n",
" \"name\": \"python\",\n",
" \"version\": \"3.14.0\"\n",
" }\n",
" },\n",
" \"nbformat\": 4,\n",
" \"nbformat_minor\": 5\n",
"}"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}