[1] data_structures #186

Merged
kit8nino merged 13 commits from pomelovsd/2026-rff_mp:data_structures into develop 2026-05-30 11:37:01 +00:00
8 changed files with 1052 additions and 0 deletions

View File

@ -0,0 +1,58 @@
def create_node(name, phone):
return {"name": name, "phone": phone, "left": None, "right": None}
def bst_insert(root, name, phone):
if root is None:
return create_node(name, phone)
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_insert_sort(sorted_data, left, right):
if left > right:
return None
mid = (left + right) // 2
name, phone = sorted_data[mid]
root = create_node(name, phone)
root["left"] = bst_insert_sort(sorted_data, left, mid - 1)
root["right"] = bst_insert_sort(sorted_data, mid + 1, right)
return root
def bst_find(root, name):
if root is None:
return None
if name == root["name"]:
return root["phone"]
if name < root["name"]:
return bst_find(root["left"], name)
return bst_find(root["right"], name)
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"]
# Два ребенка
current = root["right"]
while current["left"] is not None:
current = current["left"]
root["name"] = current["name"]
root["phone"] = current["phone"]
# Удаляем преемника
root["right"] = bst_delete(root["right"], current["name"])
return root

View File

@ -0,0 +1,30 @@
from LinkedList import ll_insert, ll_find, ll_delete, ll_list_all
def create_ht(size = 1000):
return[None] * size
def hash_function(name, size = 1000):
value = 0
for char in name:
value = (value * 31 + ord(char)) % size
return value
def ht_insert(buckets, name, phone):
index = hash_function(name, len(buckets))
buckets[index] = ll_insert(buckets[index], name, phone)
return buckets
def ht_delete(buckets, name):
index = hash_function(name, len(buckets))
buckets[index] = ll_delete(buckets[index], name)
return buckets
def ht_find(buckets, name):
index = hash_function(name, len(buckets))
return ll_find(buckets[index], name)
def ht_list_all(buckets):
records = []
for bucket in buckets:
if buckets is not None:
records.extend(ll_list_all(buckets))

View File

@ -0,0 +1,60 @@
# Создание узла
def create_node(name, phone):
return {"name": name, "phone": phone, "next": None}
def ll_insert(head, name, phone):
node = create_node(name, phone)
# Случай для пустого списка
if head is None:
return node
# Случай если надо перезаписать имя
current = head
while current:
if current["name"] == name:
current["phone"] = phone
return head
current = current["next"]
# Случай добавления нового элемента
current = head
while current["next"]:
current = current["next"]
current["next"] = node
return head
def ll_find(head, name):
current = head
while current:
if current["name"] == name:
return current["phone"]
current = current["next"]
return "Нет данных"
def ll_delete(head, name):
# Случай для пустого списка
if head is None:
return None
# Удаление головы
if head["name"] == name:
return head["next"]
# Случай для поиска элемента
current = head
while current["next"]:
if current["next"]["name"] == name:
current['next'] = current["next"]["next"]
return head
current = current['next']
return head
def ll_list_all(head):
records = []
current = head
while current:
records.append((current["name"],current["phone"]))
current = current["next"]
records.sort(key=lambda x: x[0]) # Сортировка элементов по алфавиту
return records

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,19 @@
Структура,Режим,Операция,Время (сек)
LinkedList,случайный,вставка,7.90476148960006
LinkedList,сортированный,вставка,5.470369223799935
LinkedList,случайный,поиск,0.043889598400346584
LinkedList,сортированный,поиск,0.04527814500015666
LinkedList,случайный,удаление,0.03798479180004506
LinkedList,сортированный,удаление,0.020613410200166982
HashTable,случайный,вставка,0.06718570920002094
HashTable,сортированный,вставка,0.015257699599897024
HashTable,случайный,поиск,0.00032641679972584826
HashTable,сортированный,поиск,0.0003182652002578834
HashTable,случайный,удаление,0.00020438940009626094
HashTable,сортированный,удаление,0.00020722279987239745
BinaryTree,случайный,вставка,0.025759428999845114
BinaryTree,сортированный,вставка,0.00637738920013362
BinaryTree,случайный,поиск,0.00039911679978104074
BinaryTree,сортированный,поиск,0.00043057159964519085
BinaryTree,случайный,удаление,0.00042884459980996326
BinaryTree,сортированный,удаление,0.0005684383997504483
1 Структура Режим Операция Время (сек)
2 LinkedList случайный вставка 7.90476148960006
3 LinkedList сортированный вставка 5.470369223799935
4 LinkedList случайный поиск 0.043889598400346584
5 LinkedList сортированный поиск 0.04527814500015666
6 LinkedList случайный удаление 0.03798479180004506
7 LinkedList сортированный удаление 0.020613410200166982
8 HashTable случайный вставка 0.06718570920002094
9 HashTable сортированный вставка 0.015257699599897024
10 HashTable случайный поиск 0.00032641679972584826
11 HashTable сортированный поиск 0.0003182652002578834
12 HashTable случайный удаление 0.00020438940009626094
13 HashTable сортированный удаление 0.00020722279987239745
14 BinaryTree случайный вставка 0.025759428999845114
15 BinaryTree сортированный вставка 0.00637738920013362
16 BinaryTree случайный поиск 0.00039911679978104074
17 BinaryTree сортированный поиск 0.00043057159964519085
18 BinaryTree случайный удаление 0.00042884459980996326
19 BinaryTree сортированный удаление 0.0005684383997504483

View File

@ -0,0 +1,41 @@
# Предложенные вопросы:
## Сравните:
1) Как порядок входных данных влияет на скорость вставки в BST(деградация до O(n) на отсортированных данных).
2) Почему хеш-таблица почти не чувствительна к порядку.
3) Почему связный список всегда медленен при поиске.
4) Как удаление работает в каждой структуре.
5) Вывод должен содержать ответ на вопрос: какую структуру и для каких задач (частые вставки, частый поиск, необходимость получать данные в порядке) стоит выбирать в реальной жизни.*
# Анализ результатов:
![[analysis.png]]
![[analysis_midle.png]]
>График созданный для на основе замеров времени работы разных типов данных
>P.s. Данные на графиках не точные, а приблизительные, из-за во многом случайных замеров значений
## Выводы:
### 1) **Как порядок входных данных влияет на скорость вставки в BST?**
Порядок отличается очень сильно, если в обычном случае сложность равна $O(log(n))$, а в худшем случае(как раз в случае отсортированных данных) равна $O(n)$.
>В моём случае время работы мало отличимо так как, во время замеров, я заметил, что данные записываются крайне долго за счёт особенностей реализации(бинарное дерево вырождалось в связный список) и пришлось добавить ещё одну функцию, которая будет искусственно разбивать отсортированный массив на 2 ветки, а не записывать все ветви подряд
### 2) **Почему хеш-таблица почти не чувствительна к порядку?**
Из-за особенностей записи данных в память. Хеш-таблица вычисляет, номер строки при помощи формулы т.е мы можем найти любой сколь угодный элемент за $O(1)$
### 3) **Почему связный список всегда медленен при поиске?**
Из-за способа записи. Так-как мы можем добраться до следующего элемента только путём перебора равного номеру поисковой строки, при сложности $O(n)$
### 4) Как удаление работает в каждой структуре?
- **Связный список**
Рассматривается 3 случая:
1) Если список пустой, **возращаем пустой список**
2) Если удаляем голову, то **возвращаем, как голову следующий элемент списка**
3) Если мы удаляем промежуточный элемент, ищем нужный элемент а потом **подменяем элементу стоящем перед элементом, который мы ищем ссылку элемента идущему после удаления**
- **Хеш-таблица**
Реализация считает при помощи Хеш-ключа, номер элемента
> P.s. В моей реализации Хеш-таблица и связный список схожи по реализации, потому что Хеш-таблица использует функцию связного списка)
- **Бинарное дерево**
Рассмотрим так же 4 случая(немного схожа со связным списком с поправкой на то, что потомок может быть не один):
1) Если список пустой, **возращаем пустой список**
2) Если элемент слева, то **спускаемся в левую ветвь**
3) Если элемент справа, то **спускаемся в правую ветвь**
4) Если ветки 2, то **как-то оцениваем обе вершины и двигаемся к нужному результату**
При нахождении элемента элементу слева от найденного передаём ссылку на правый от найденного элемента и наоборот левому элементу ссылку на правый
###
5) Какую структуру и для каких задач (частые вставки, частый поиск, необходимость получать данные в порядке) стоит выбирать в реальной жизни?
- Для частых вставок и поиска элементов следует использовать Хеш-таблицы, из-за особенностей добавления (определение номера в таблицы при помощи математической формулы, а не порядковым номером)
- В случае, если нам надо использовать упорядоченные данные, то следует использовать бинарное дерево(из-за особенностей хранения)
>P.s. Вывод 0) Как же долго работает функция print()...