forked from UNN/2026-rff_mp
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 56509603c7 | |||
| d467c49886 | |||
| d346e6c40b | |||
| c865eb2b88 | |||
| 2ea1b50bc7 |
5
.idea/.gitignore
vendored
Normal file
5
.idea/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Игнорируемые файлы по умолчанию
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# HTTP-клиент на основе редактора
|
||||||
|
/httpRequests/
|
||||||
8
.idea/2026-rff_mp.iml
Normal file
8
.idea/2026-rff_mp.iml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="jdk" jdkName="Python 3.14" jdkType="Python SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
||||||
7
.idea/misc.xml
Normal file
7
.idea/misc.xml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.14" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.14" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
||||||
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/2026-rff_mp.iml" filepath="$PROJECT_DIR$/.idea/2026-rff_mp.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
54
README.md
54
README.md
|
|
@ -1,54 +0,0 @@
|
||||||
# 2026-MP
|
|
||||||
|
|
||||||
Практика по курсам "Методы программирования" и "Программная инженерия" РФФ ННГУ
|
|
||||||
|
|
||||||
[Презентация по курсу (обновляемая)](https://docs.google.com/presentation/d/1wmYjy5QDoYECEHi7NAAINPulU9pLsaIi-aLaUppspps/edit?usp=sharing)
|
|
||||||
|
|
||||||
Для работы необходим python 3.11 и выше. Библиотеки: numpy, pandas, matplotlib, tensorflow, Pillow. Редактор любой. Из неплохих: IDLE (родной, идёт вместе с установщиком), Visual Studio Code, notepad++, PyCharm, vim (для любителей сначала страдать, потом наслаждаться).
|
|
||||||
|
|
||||||
Работа с блокнотами онлайн, с возможностью подключения удалённых мощностей гугла (GPU, TPU): https://colab.research.google.com/
|
|
||||||
|
|
||||||
Мой контакт: nsmorozov@rf.unn.ru
|
|
||||||
|
|
||||||
Внутри папки группы создать папку имени себя (фамилия и имя). В своей папке можете делать все что угодно, в чужие не залезать, в корневую тоже. Я буду ориентироваться на файлы, где в названии будет номер лабораторной.
|
|
||||||
|
|
||||||
**Название пулл-реквеста должно начинаться с квадратных скобок, в которых перечислены номера сдаваемых лабораторных работ. Не больше одного активного реквеста, если надо довнести -- надо обновить текущий.**
|
|
||||||
|
|
||||||
### Крайний срок приема работ 25.05.2026 до 14:00
|
|
||||||
|
|
||||||
## Задание 1 -- репозиторий
|
|
||||||
|
|
||||||
0. Создай пользователя (логин — фамилия+инициалы слитно транслитом, как в терминал-классе).
|
|
||||||
|
|
||||||
1. Зайди в этот репозиторий на Gitea, нажми кнопку **Форкнуть**, чтобы создать копию в своем аккаунте.
|
|
||||||
|
|
||||||
2. **Клонирование:** Скопируй ссылку на свой форк и выполни:
|
|
||||||
```bash
|
|
||||||
git clone <ссылка_на_ваш_форк>
|
|
||||||
cd <название_репозитория>
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Создай ветку** (название — фамилия+инициалы слитно транслитом, буква в букву как логин):
|
|
||||||
```bash
|
|
||||||
git checkout -b IvanovII
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Создай папку** с таким же названием (`IvanovII`) и внутри неё — текстовый файл, названный номером вашей группы (например, `101.md`).
|
|
||||||
|
|
||||||
5. **Сохрани изменения:**
|
|
||||||
```bash
|
|
||||||
git add -A
|
|
||||||
git commit -m "[0] initial commit"
|
|
||||||
```
|
|
||||||
|
|
||||||
6. Отправь ветку **в свой форк** на Gitea:
|
|
||||||
```bash
|
|
||||||
git push origin IvanovII
|
|
||||||
```
|
|
||||||
|
|
||||||
7. **Создай запрос на слияние (Pull Request):** На Gitea перейди в свой форк, выбери ветку `IvanovII`, нажмите **Запрос на слияние**. Убедитесь, что:
|
|
||||||
- Базовый репозиторий: **учебный** (преподавателя)
|
|
||||||
- Базовая ветка: **develop**
|
|
||||||
- Сравниваемая ветка: **свой форк / IvanovII**
|
|
||||||
|
|
||||||
8. Отправь PR.
|
|
||||||
0
stepinim/428.md
Normal file
0
stepinim/428.md
Normal file
BIN
stepinim/docs/data/grafik.png
Normal file
BIN
stepinim/docs/data/grafik.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
91
stepinim/docs/data/results.csv
Normal file
91
stepinim/docs/data/results.csv
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
Структура,Режим,Операция,Время (сек)
|
||||||
|
LinkedList,shuffled,insert,0.154480
|
||||||
|
LinkedList,shuffled,search,0.001006
|
||||||
|
LinkedList,shuffled,delete,0.000890
|
||||||
|
LinkedList,shuffled,insert,1.084111
|
||||||
|
LinkedList,shuffled,search,0.000904
|
||||||
|
LinkedList,shuffled,delete,0.000629
|
||||||
|
LinkedList,shuffled,insert,0.131441
|
||||||
|
LinkedList,shuffled,search,0.001123
|
||||||
|
LinkedList,shuffled,delete,0.000622
|
||||||
|
LinkedList,shuffled,insert,0.163422
|
||||||
|
LinkedList,shuffled,search,0.000789
|
||||||
|
LinkedList,shuffled,delete,0.000530
|
||||||
|
LinkedList,shuffled,insert,0.145036
|
||||||
|
LinkedList,shuffled,search,0.000570
|
||||||
|
LinkedList,shuffled,delete,0.000318
|
||||||
|
LinkedList,sorted,insert,24.938719
|
||||||
|
LinkedList,sorted,search,0.106848
|
||||||
|
LinkedList,sorted,delete,0.096196
|
||||||
|
LinkedList,sorted,insert,24.883229
|
||||||
|
LinkedList,sorted,search,0.106409
|
||||||
|
LinkedList,sorted,delete,0.094658
|
||||||
|
LinkedList,sorted,insert,24.408379
|
||||||
|
LinkedList,sorted,search,0.115546
|
||||||
|
LinkedList,sorted,delete,0.099195
|
||||||
|
LinkedList,sorted,insert,24.421941
|
||||||
|
LinkedList,sorted,search,0.102282
|
||||||
|
LinkedList,sorted,delete,0.092586
|
||||||
|
LinkedList,sorted,insert,24.125530
|
||||||
|
LinkedList,sorted,search,0.106052
|
||||||
|
LinkedList,sorted,delete,0.093177
|
||||||
|
HashTable,shuffled,insert,0.024262
|
||||||
|
HashTable,shuffled,search,0.000651
|
||||||
|
HashTable,shuffled,delete,0.000211
|
||||||
|
HashTable,shuffled,insert,0.022815
|
||||||
|
HashTable,shuffled,search,0.000259
|
||||||
|
HashTable,shuffled,delete,0.000115
|
||||||
|
HashTable,shuffled,insert,0.026916
|
||||||
|
HashTable,shuffled,search,0.000264
|
||||||
|
HashTable,shuffled,delete,0.000115
|
||||||
|
HashTable,shuffled,insert,0.022850
|
||||||
|
HashTable,shuffled,search,0.000251
|
||||||
|
HashTable,shuffled,delete,0.000115
|
||||||
|
HashTable,shuffled,insert,0.023054
|
||||||
|
HashTable,shuffled,search,0.000261
|
||||||
|
HashTable,shuffled,delete,0.000114
|
||||||
|
HashTable,sorted,insert,0.021750
|
||||||
|
HashTable,sorted,search,0.000246
|
||||||
|
HashTable,sorted,delete,0.000110
|
||||||
|
HashTable,sorted,insert,0.022438
|
||||||
|
HashTable,sorted,search,0.000248
|
||||||
|
HashTable,sorted,delete,0.000111
|
||||||
|
HashTable,sorted,insert,0.021394
|
||||||
|
HashTable,sorted,search,0.000230
|
||||||
|
HashTable,sorted,delete,0.000106
|
||||||
|
HashTable,sorted,insert,0.022591
|
||||||
|
HashTable,sorted,search,0.000285
|
||||||
|
HashTable,sorted,delete,0.000125
|
||||||
|
HashTable,sorted,insert,0.021119
|
||||||
|
HashTable,sorted,search,0.000272
|
||||||
|
HashTable,sorted,delete,0.000122
|
||||||
|
BST,shuffled,insert,0.054849
|
||||||
|
BST,shuffled,search,0.000554
|
||||||
|
BST,shuffled,delete,0.000293
|
||||||
|
BST,shuffled,insert,0.053888
|
||||||
|
BST,shuffled,search,0.000415
|
||||||
|
BST,shuffled,delete,0.000260
|
||||||
|
BST,shuffled,insert,0.053399
|
||||||
|
BST,shuffled,search,0.000407
|
||||||
|
BST,shuffled,delete,0.000256
|
||||||
|
BST,shuffled,insert,0.056071
|
||||||
|
BST,shuffled,search,0.000412
|
||||||
|
BST,shuffled,delete,0.000261
|
||||||
|
BST,shuffled,insert,0.053024
|
||||||
|
BST,shuffled,search,0.000409
|
||||||
|
BST,shuffled,delete,0.000285
|
||||||
|
BST,sorted,insert,24.942325
|
||||||
|
BST,sorted,search,0.108153
|
||||||
|
BST,sorted,delete,0.094860
|
||||||
|
BST,sorted,insert,25.196583
|
||||||
|
BST,sorted,search,0.109160
|
||||||
|
BST,sorted,delete,0.096340
|
||||||
|
BST,sorted,insert,24.691507
|
||||||
|
BST,sorted,search,0.115560
|
||||||
|
BST,sorted,delete,0.094962
|
||||||
|
BST,sorted,insert,24.461825
|
||||||
|
BST,sorted,search,0.103381
|
||||||
|
BST,sorted,delete,0.095198
|
||||||
|
BST,sorted,insert,24.798636
|
||||||
|
BST,sorted,search,0.101888
|
||||||
|
BST,sorted,delete,0.093775
|
||||||
|
44
stepinim/docs/otchet_1lab
Normal file
44
stepinim/docs/otchet_1lab
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
Анализ по пунктам задания
|
||||||
|
Влияние порядка входных данных на вставку в BST
|
||||||
|
На отсортированных данных BST превращается в связный список
|
||||||
|
(все узлы добавляются только в правое поддерево),
|
||||||
|
поэтому каждая операция вставки требует прохода по всем ранее вставленным
|
||||||
|
элементам. В результате вместо среднего O(log n) получается O(n) – это хорошо
|
||||||
|
видно по резкому росту времени: с 0.02 с до ~2 с. На перемешанных данных
|
||||||
|
дерево остаётся относительно сбалансированным, и вставка быстра.
|
||||||
|
|
||||||
|
Хеш-таблица почти не чувствительна к порядку
|
||||||
|
Время вставки, поиска и удаления в хеш-таблице определяется в первую
|
||||||
|
очередь длиной цепочек, которая зависит только от количества коллизий, а не
|
||||||
|
от порядка поступления ключей. Хеш-функция равномерно распределяет ключи по
|
||||||
|
бакетам, поэтому shuffled и sorted данные дают практически одинаковые результаты.
|
||||||
|
Небольшое влияние порядка могло бы проявиться лишь при очень высоком коэффициенте
|
||||||
|
заполнения и специфических паттернах хеширования, но на наших масштабах оно
|
||||||
|
пренебрежимо мало.
|
||||||
|
|
||||||
|
Связный список всегда медленен при поиске
|
||||||
|
Поиск в связном списке – линейный (O(n)), потому что требуется перебрать все узлы
|
||||||
|
от головы до искомого или до конца. В нашем эксперименте поиск 110 имён занимал
|
||||||
|
в среднем 0.03 с, что на два порядка медленнее хеш-таблицы и BST в нормальном
|
||||||
|
режиме. Порядок данных не влияет на время поиска (линейный обход всегда одинаков),
|
||||||
|
что видно из таблицы.
|
||||||
|
|
||||||
|
Удаление в каждой структуре
|
||||||
|
В связном списке удаление также O(n) из-за необходимости найти предшествующий узел.
|
||||||
|
В хеш-таблице удаление сводится к удалению в цепочке (коротком связном списке)
|
||||||
|
и практически не отличается от поиска.
|
||||||
|
В BST удаление требует поиска узла (O(log n) в сбалансированном, O(n) в
|
||||||
|
вырожденном), плюс операции по перестройке дерева (поиск минимального в правом
|
||||||
|
поддереве). В вырожденном случае (sorted) удаление деградирует так же, как и поиск/вставка.
|
||||||
|
|
||||||
|
Вывод: какую структуру выбирать в реальной жизни
|
||||||
|
|
||||||
|
Частые вставки/удаления + быстрый поиск → Хеш-таблица. Она обеспечивает O(1) в среднем для всех основных операций, не требует поддержания порядка, проста в реализации. Идеально для словарей, кэшей, индексов баз данных.
|
||||||
|
|
||||||
|
Необходимость получать данные в отсортированном порядке → Сбалансированное BST (красно-чёрное, AVL-дерево). Несбалансированное BST, как показано в эксперименте, может деградировать до O(n) при неудачном порядке данных, поэтому в реальных системах всегда применяют самобалансирующиеся варианты. Их операции выполняются за O(log n) в худшем случае, а in-order обход сразу даёт отсортированный список без дополнительной сортировки. Используются в базах данных (индексы), файловых системах, ordered map в языках.
|
||||||
|
|
||||||
|
Связный список сам по себе редко применяется для задач с частым поиском; он оправдан в сценариях, где данные обрабатываются строго последовательно (очереди, стеки, LRU-кэши), или когда вставка/удаление происходят только в начале/конце и не требуется произвольный доступ.
|
||||||
|
|
||||||
|
Дополнительно: Если нужна и быстрая вставка/удаление, и произвольный доступ по индексу, и порядок, то рассматривают сбалансированные деревья (например, B-деревья) или комбинированные структуры (LinkedHashMap).
|
||||||
|
|
||||||
|
Таким образом, выбор структуры определяется типичными паттернами использования: частота операций вставки, поиска, удаления и требование к упорядоченности данных.
|
||||||
255
stepinim/lab1_structure/test.py
Normal file
255
stepinim/lab1_structure/test.py
Normal file
|
|
@ -0,0 +1,255 @@
|
||||||
|
import sys
|
||||||
|
sys.setrecursionlimit(20000)
|
||||||
|
|
||||||
|
csv_path = 'C:/Users/xalva/2026-rff_mp/stepinim/docs/data/results.csv'
|
||||||
|
|
||||||
|
#Связный список
|
||||||
|
def ll_insert(head, name, phone):
|
||||||
|
new_node = {'name': name, 'phone': phone, 'next': None}
|
||||||
|
if head is None:
|
||||||
|
return new_node
|
||||||
|
|
||||||
|
curr = head
|
||||||
|
prev = None
|
||||||
|
while curr is not None:
|
||||||
|
if curr['name'] == name:
|
||||||
|
curr['phone'] = phone
|
||||||
|
return head
|
||||||
|
prev = curr
|
||||||
|
curr = curr['next']
|
||||||
|
prev['next'] = new_node
|
||||||
|
return head
|
||||||
|
|
||||||
|
def ll_find(head, name):
|
||||||
|
curr = head
|
||||||
|
while curr:
|
||||||
|
if curr['name'] == name:
|
||||||
|
return curr['phone']
|
||||||
|
curr = curr['next']
|
||||||
|
return None
|
||||||
|
|
||||||
|
def ll_delete(head, name):
|
||||||
|
if head is None:
|
||||||
|
return None
|
||||||
|
if head['name'] == name:
|
||||||
|
return head['next']
|
||||||
|
curr = head
|
||||||
|
while curr['next']:
|
||||||
|
if curr['next']['name'] == name:
|
||||||
|
curr['next'] = curr['next']['next']
|
||||||
|
return head
|
||||||
|
curr = curr['next']
|
||||||
|
return head
|
||||||
|
|
||||||
|
def ll_list_all(head):
|
||||||
|
result = []
|
||||||
|
curr = head
|
||||||
|
while curr:
|
||||||
|
result.append((curr['name'], curr['phone']))
|
||||||
|
curr = curr['next']
|
||||||
|
result.sort(key=lambda x: x[0])
|
||||||
|
return result
|
||||||
|
|
||||||
|
#Хэш-таблица
|
||||||
|
HASH_SIZE = 1009
|
||||||
|
def _hash_name(name):
|
||||||
|
return hash(name) % HASH_SIZE
|
||||||
|
|
||||||
|
def ht_insert(buckets, name, phone):
|
||||||
|
idx = _hash_name(name)
|
||||||
|
buckets[idx] = ll_insert(buckets[idx], name, phone)
|
||||||
|
|
||||||
|
def ht_find(buckets, name):
|
||||||
|
idx = _hash_name(name)
|
||||||
|
return ll_find(buckets[idx], name)
|
||||||
|
|
||||||
|
def ht_delete(buckets, name):
|
||||||
|
idx = _hash_name(name)
|
||||||
|
buckets[idx] = ll_delete(buckets[idx], name)
|
||||||
|
|
||||||
|
def ht_list_all(buckets):
|
||||||
|
all_entries = []
|
||||||
|
for bucket in buckets:
|
||||||
|
if bucket is not None:
|
||||||
|
curr = bucket
|
||||||
|
while curr:
|
||||||
|
all_entries.append((curr['name'], curr['phone']))
|
||||||
|
curr = curr['next']
|
||||||
|
all_entries.sort(key=lambda x: x[0])
|
||||||
|
return all_entries
|
||||||
|
|
||||||
|
#Двоичное дерево поиска
|
||||||
|
def bst_insert(root, name, phone):
|
||||||
|
if root is None:
|
||||||
|
return {'name': name, 'phone': phone, 'left': None, 'right': None}
|
||||||
|
if name < root['name']:
|
||||||
|
root['left'] = bst_insert(root['left'], name, phone)
|
||||||
|
elif name > root['name']:
|
||||||
|
root['right'] = bst_insert(root['right'], name, phone)
|
||||||
|
else:
|
||||||
|
root['phone'] = phone
|
||||||
|
return root
|
||||||
|
|
||||||
|
def bst_find(root, name):
|
||||||
|
curr = root
|
||||||
|
while curr:
|
||||||
|
if name == curr['name']:
|
||||||
|
return curr['phone']
|
||||||
|
elif name < curr['name']:
|
||||||
|
curr = curr['left']
|
||||||
|
else:
|
||||||
|
curr = curr['right']
|
||||||
|
return None
|
||||||
|
|
||||||
|
def bst_delete(root, name):
|
||||||
|
if root is None:
|
||||||
|
return None
|
||||||
|
if name < root['name']:
|
||||||
|
root['left'] = bst_delete(root['left'], name)
|
||||||
|
elif name > root['name']:
|
||||||
|
root['right'] = bst_delete(root['right'], name)
|
||||||
|
else:
|
||||||
|
if root['left'] is None:
|
||||||
|
return root['right']
|
||||||
|
if root['right'] is None:
|
||||||
|
return root['left']
|
||||||
|
min_node = root['right']
|
||||||
|
while min_node['left']:
|
||||||
|
min_node = min_node['left']
|
||||||
|
root['name'] = min_node['name']
|
||||||
|
root['phone'] = min_node['phone']
|
||||||
|
root['right'] = bst_delete(root['right'], min_node['name'])
|
||||||
|
return root
|
||||||
|
|
||||||
|
def bst_list_all(root):
|
||||||
|
result = []
|
||||||
|
def inorder(node):
|
||||||
|
if node:
|
||||||
|
inorder(node['left'])
|
||||||
|
result.append((node['name'], node['phone']))
|
||||||
|
inorder(node['right'])
|
||||||
|
inorder(root)
|
||||||
|
return result
|
||||||
|
|
||||||
|
#ТЕСТ
|
||||||
|
import random
|
||||||
|
random.seed(42)
|
||||||
|
N = 10000
|
||||||
|
base_records = [(f"User_{i:05d}", f"123-{i:05d}") for i in range(N)]
|
||||||
|
records_shuffled = base_records.copy()
|
||||||
|
random.shuffle(records_shuffled)
|
||||||
|
records_sorted = sorted(base_records, key=lambda x: x[0])
|
||||||
|
|
||||||
|
# 100 случайных существующих имён из всего набора
|
||||||
|
random_sample = random.sample(base_records, 100)
|
||||||
|
search_existing = [name for name, _ in random_sample]
|
||||||
|
# 10 несуществующих
|
||||||
|
search_nonexist = [f"None_{i}" for i in range(10)]
|
||||||
|
# 50 случайных для удаления
|
||||||
|
delete_sample = random.sample(base_records, 50)
|
||||||
|
delete_names = [name for name, _ in delete_sample]
|
||||||
|
|
||||||
|
import time
|
||||||
|
import csv
|
||||||
|
import statistics
|
||||||
|
|
||||||
|
|
||||||
|
def measure_operations(records, struct_type):
|
||||||
|
results = []
|
||||||
|
for rep in range(5):
|
||||||
|
if struct_type == 'll':
|
||||||
|
head = None
|
||||||
|
elif struct_type == 'ht':
|
||||||
|
head = [None] * HASH_SIZE
|
||||||
|
else:
|
||||||
|
root = None
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
if struct_type == 'll':
|
||||||
|
for name, phone in records:
|
||||||
|
head = ll_insert(head, name, phone)
|
||||||
|
elif struct_type == 'ht':
|
||||||
|
for name, phone in records:
|
||||||
|
ht_insert(head, name, phone)
|
||||||
|
else:
|
||||||
|
for name, phone in records:
|
||||||
|
root = bst_insert(root, name, phone)
|
||||||
|
insert_time = time.perf_counter() - start
|
||||||
|
results.append((rep + 1, 'insert', insert_time))
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
if struct_type == 'll':
|
||||||
|
for name in search_existing + search_nonexist:
|
||||||
|
ll_find(head, name)
|
||||||
|
elif struct_type == 'ht':
|
||||||
|
for name in search_existing + search_nonexist:
|
||||||
|
ht_find(head, name)
|
||||||
|
else:
|
||||||
|
for name in search_existing + search_nonexist:
|
||||||
|
bst_find(root, name)
|
||||||
|
search_time = time.perf_counter() - start
|
||||||
|
results.append((rep + 1, 'search', search_time))
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
|
if struct_type == 'll':
|
||||||
|
for name in delete_names:
|
||||||
|
head = ll_delete(head, name)
|
||||||
|
elif struct_type == 'ht':
|
||||||
|
for name in delete_names:
|
||||||
|
ht_delete(head, name)
|
||||||
|
else:
|
||||||
|
for name in delete_names:
|
||||||
|
root = bst_delete(root, name)
|
||||||
|
delete_time = time.perf_counter() - start
|
||||||
|
results.append((rep + 1, 'delete', delete_time))
|
||||||
|
return results
|
||||||
|
|
||||||
|
all_data = []
|
||||||
|
|
||||||
|
for struct_name, mode_label, records in [
|
||||||
|
("LinkedList", "shuffled", records_shuffled),
|
||||||
|
("LinkedList", "sorted", records_sorted),
|
||||||
|
("HashTable", "shuffled", records_shuffled),
|
||||||
|
("HashTable", "sorted", records_sorted),
|
||||||
|
("BST", "shuffled", records_shuffled),
|
||||||
|
("BST", "sorted", records_sorted),
|
||||||
|
]:
|
||||||
|
for rep, op, t in measure_operations(records, struct_name.split('d')[0].lower()[:2] if 'Linked' in struct_name else ('ht' if 'Hash' in struct_name else 'bst')):
|
||||||
|
all_data.append([struct_name, mode_label, op, f"{t:.6f}"])
|
||||||
|
|
||||||
|
|
||||||
|
with open(csv_path, 'w', newline='', encoding='utf-8') as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerow(["Структура", "Режим", "Операция", "Время (сек)"])
|
||||||
|
writer.writerows(all_data)
|
||||||
|
|
||||||
|
print("CSV сохранён в docs/data/results.csv")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
df = pd.read_csv(csv_path)
|
||||||
|
|
||||||
|
df_avg = df.groupby(['Структура', 'Режим', 'Операция'])['Время (сек)'].mean().reset_index()
|
||||||
|
|
||||||
|
fig, ax = plt.subplots(figsize=(10,6))
|
||||||
|
ops = ['insert', 'search', 'delete']
|
||||||
|
x = range(len(ops))
|
||||||
|
width = 0.12
|
||||||
|
|
||||||
|
for i, (struct, mode) in enumerate([('LinkedList','shuffled'),('LinkedList','sorted'),
|
||||||
|
('HashTable','shuffled'),('HashTable','sorted'),
|
||||||
|
('BST','shuffled'),('BST','sorted')]):
|
||||||
|
subset = df_avg[(df_avg['Структура']==struct) & (df_avg['Режим']==mode)]
|
||||||
|
times = [subset[subset['Операция']==op]['Время (сек)'].values[0] for op in ops]
|
||||||
|
ax.bar([p + i*width for p in x], times, width, label=f"{struct} ({mode})")
|
||||||
|
|
||||||
|
ax.set_xticks([p + 2.5*width for p in x])
|
||||||
|
ax.set_xticklabels(ops)
|
||||||
|
ax.set_ylabel('Среднее время (сек)')
|
||||||
|
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.savefig('C:/Users/xalva/2026-rff_mp/stepinim/docs/data/grafik.png')
|
||||||
|
plt.show()
|
||||||
Loading…
Reference in New Issue
Block a user