Compare commits

...

5 Commits

Author SHA1 Message Date
56509603c7 [3]lab1_test 2026-04-28 21:25:45 +03:00
d467c49886 [2]new_sistem 2026-04-11 20:34:09 +03:00
d346e6c40b [2]proverka 2026-02-21 12:42:55 +03:00
c865eb2b88 [1]nachlo 2026-02-21 12:41:07 +03:00
2ea1b50bc7 [0] initial commit 2026-02-20 22:50:08 +03:00
12 changed files with 430 additions and 54 deletions

5
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Игнорируемые файлы по умолчанию
/shelf/
/workspace.xml
# HTTP-клиент на основе редактора
/httpRequests/

8
.idea/2026-rff_mp.iml Normal file
View 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>

View 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
View 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
View 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
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -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
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View 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
1 Структура Режим Операция Время (сек)
2 LinkedList shuffled insert 0.154480
3 LinkedList shuffled search 0.001006
4 LinkedList shuffled delete 0.000890
5 LinkedList shuffled insert 1.084111
6 LinkedList shuffled search 0.000904
7 LinkedList shuffled delete 0.000629
8 LinkedList shuffled insert 0.131441
9 LinkedList shuffled search 0.001123
10 LinkedList shuffled delete 0.000622
11 LinkedList shuffled insert 0.163422
12 LinkedList shuffled search 0.000789
13 LinkedList shuffled delete 0.000530
14 LinkedList shuffled insert 0.145036
15 LinkedList shuffled search 0.000570
16 LinkedList shuffled delete 0.000318
17 LinkedList sorted insert 24.938719
18 LinkedList sorted search 0.106848
19 LinkedList sorted delete 0.096196
20 LinkedList sorted insert 24.883229
21 LinkedList sorted search 0.106409
22 LinkedList sorted delete 0.094658
23 LinkedList sorted insert 24.408379
24 LinkedList sorted search 0.115546
25 LinkedList sorted delete 0.099195
26 LinkedList sorted insert 24.421941
27 LinkedList sorted search 0.102282
28 LinkedList sorted delete 0.092586
29 LinkedList sorted insert 24.125530
30 LinkedList sorted search 0.106052
31 LinkedList sorted delete 0.093177
32 HashTable shuffled insert 0.024262
33 HashTable shuffled search 0.000651
34 HashTable shuffled delete 0.000211
35 HashTable shuffled insert 0.022815
36 HashTable shuffled search 0.000259
37 HashTable shuffled delete 0.000115
38 HashTable shuffled insert 0.026916
39 HashTable shuffled search 0.000264
40 HashTable shuffled delete 0.000115
41 HashTable shuffled insert 0.022850
42 HashTable shuffled search 0.000251
43 HashTable shuffled delete 0.000115
44 HashTable shuffled insert 0.023054
45 HashTable shuffled search 0.000261
46 HashTable shuffled delete 0.000114
47 HashTable sorted insert 0.021750
48 HashTable sorted search 0.000246
49 HashTable sorted delete 0.000110
50 HashTable sorted insert 0.022438
51 HashTable sorted search 0.000248
52 HashTable sorted delete 0.000111
53 HashTable sorted insert 0.021394
54 HashTable sorted search 0.000230
55 HashTable sorted delete 0.000106
56 HashTable sorted insert 0.022591
57 HashTable sorted search 0.000285
58 HashTable sorted delete 0.000125
59 HashTable sorted insert 0.021119
60 HashTable sorted search 0.000272
61 HashTable sorted delete 0.000122
62 BST shuffled insert 0.054849
63 BST shuffled search 0.000554
64 BST shuffled delete 0.000293
65 BST shuffled insert 0.053888
66 BST shuffled search 0.000415
67 BST shuffled delete 0.000260
68 BST shuffled insert 0.053399
69 BST shuffled search 0.000407
70 BST shuffled delete 0.000256
71 BST shuffled insert 0.056071
72 BST shuffled search 0.000412
73 BST shuffled delete 0.000261
74 BST shuffled insert 0.053024
75 BST shuffled search 0.000409
76 BST shuffled delete 0.000285
77 BST sorted insert 24.942325
78 BST sorted search 0.108153
79 BST sorted delete 0.094860
80 BST sorted insert 25.196583
81 BST sorted search 0.109160
82 BST sorted delete 0.096340
83 BST sorted insert 24.691507
84 BST sorted search 0.115560
85 BST sorted delete 0.094962
86 BST sorted insert 24.461825
87 BST sorted search 0.103381
88 BST sorted delete 0.095198
89 BST sorted insert 24.798636
90 BST sorted search 0.101888
91 BST sorted delete 0.093775

44
stepinim/docs/otchet_1lab Normal file
View 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).
Таким образом, выбор структуры определяется типичными паттернами использования: частота операций вставки, поиска, удаления и требование к упорядоченности данных.

View 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()