Compare commits

...

10 Commits

7 changed files with 1050 additions and 0 deletions

View File

@ -0,0 +1,59 @@
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: 126 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,19 @@
Структура,Режим,Операция,Время (сек)
LinkedList,случайный,вставка,5.446558486199502
LinkedList,сортированный,вставка,4.543784373601374
LinkedList,случайный,поиск,0.04706894100017962
LinkedList,сортированный,поиск,0.04769594539902755
LinkedList,случайный,удаление,0.03921282640003483
LinkedList,сортированный,удаление,0.028603866600315088
HashTable,случайный,вставка,0.04496854659882956
HashTable,сортированный,вставка,0.01674557240039576
HashTable,случайный,поиск,0.0002827729993441608
HashTable,сортированный,поиск,0.0003012509994732682
HashTable,случайный,удаление,0.0001654567997320555
HashTable,сортированный,удаление,0.00015406959937536158
BinaryTree,случайный,вставка,0.04737361820007209
BinaryTree,сортированный,вставка,0.008165915000427048
BinaryTree,случайный,поиск,0.0008410817987169139
BinaryTree,сортированный,поиск,0.0005058431990619284
BinaryTree,случайный,удаление,0.0004901104002783541
BinaryTree,сортированный,удаление,0.00044584080096683466
1 Структура Режим Операция Время (сек)
2 LinkedList случайный вставка 5.446558486199502
3 LinkedList сортированный вставка 4.543784373601374
4 LinkedList случайный поиск 0.04706894100017962
5 LinkedList сортированный поиск 0.04769594539902755
6 LinkedList случайный удаление 0.03921282640003483
7 LinkedList сортированный удаление 0.028603866600315088
8 HashTable случайный вставка 0.04496854659882956
9 HashTable сортированный вставка 0.01674557240039576
10 HashTable случайный поиск 0.0002827729993441608
11 HashTable сортированный поиск 0.0003012509994732682
12 HashTable случайный удаление 0.0001654567997320555
13 HashTable сортированный удаление 0.00015406959937536158
14 BinaryTree случайный вставка 0.04737361820007209
15 BinaryTree сортированный вставка 0.008165915000427048
16 BinaryTree случайный поиск 0.0008410817987169139
17 BinaryTree сортированный поиск 0.0005058431990619284
18 BinaryTree случайный удаление 0.0004901104002783541
19 BinaryTree сортированный удаление 0.00044584080096683466

View File

@ -0,0 +1,40 @@
# Предложенные вопросы:
## Сравните:
1) Как порядок входных данных влияет на скорость вставки в BST(деградация до O(n) на отсортированных данных).
2) Почему хеш-таблица почти не чувствительна к порядку.
3) Почему связный список всегда медленен при поиске.
4) Как удаление работает в каждой структуре.
5) Вывод должен содержать ответ на вопрос: какую структуру и для каких задач (частые вставки, частый поиск, необходимость получать данные в порядке) стоит выбирать в реальной жизни.*
# Анализ результатов:
![[analysis.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()...