{
 "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
}
