forked from UNN/2026-rff_mp
Compare commits
7 Commits
f5b0fec46f
...
dd4eca8407
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd4eca8407 | ||
|
|
b383ed1cdc | ||
|
|
9bdefcc922 | ||
|
|
0b092e8d26 | ||
|
|
b984ec3569 | ||
|
|
9c1cd94e87 | ||
|
|
8124c755f8 |
2
MusinAA/.gitignore
vendored
Normal file
2
MusinAA/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
.vscode/
|
||||
*/tests/
|
||||
0
MusinAA/task1/__init__.py
Normal file
0
MusinAA/task1/__init__.py
Normal file
88
MusinAA/task1/structures/BinaryTree.py
Normal file
88
MusinAA/task1/structures/BinaryTree.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
"""
|
||||
Двоичное дерево поиска
|
||||
|
||||
Узел — словарь:
|
||||
{'name': 'Имя', 'phone': '123', 'left': None, 'right': None}.
|
||||
"""
|
||||
|
||||
def bst_insert(root: dict|None, name: str, phone: str) -> dict:
|
||||
"""Итеративно вставляет, возвращает новый корень (если корень меняется)."""
|
||||
if root == None:
|
||||
return {'name': name, 'phone': phone, 'left': None, 'right': None}
|
||||
|
||||
# '674' < '722' == True, lol
|
||||
current = root
|
||||
while True:
|
||||
if current['name'] == name:
|
||||
current['phone'] = phone
|
||||
return root
|
||||
elif name < current['name']:
|
||||
if current['left'] == None:
|
||||
current['left'] = bst_insert(None, name, phone)
|
||||
return root
|
||||
else:
|
||||
current = current['left']
|
||||
else:
|
||||
if current['right'] == None:
|
||||
current['right'] = bst_insert(None, name, phone)
|
||||
return root
|
||||
else:
|
||||
current = current['right']
|
||||
# Увы, это самый лаконичный вариант, который я придумал.
|
||||
|
||||
|
||||
def bst_find(root: dict|None, name: str) -> str|None:
|
||||
"""Поиск в ширину."""
|
||||
node = find_node_to_delete(root, name)
|
||||
if node != None:
|
||||
return node['phone']
|
||||
|
||||
def find_node_to_delete(root: dict, name: str) -> dict|None:
|
||||
"""Поиск в ширину."""
|
||||
while root != None:
|
||||
if root['name'] == name:
|
||||
return root
|
||||
elif name < root['name']:
|
||||
root = root['left']
|
||||
else:
|
||||
root = root['right']
|
||||
return None
|
||||
|
||||
def find_minimal_child(root: dict) -> dict|None:
|
||||
while root['left']:
|
||||
root = root['left']
|
||||
return root
|
||||
|
||||
def bst_delete(root: dict, name: str) -> None:
|
||||
"""Удаляет узел и возвращает новый корень."""
|
||||
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:
|
||||
# Случай 1: нет детей или один ребенок
|
||||
if root['left'] is None:
|
||||
return root['right']
|
||||
elif root['right'] is None:
|
||||
return root['left']
|
||||
|
||||
# Случай 2: два ребенка
|
||||
min_node = find_minimal_child(root['right'])
|
||||
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: dict) -> list:
|
||||
"""Центрированный обход.
|
||||
Рекурсивно собирает записи в отсортированном порядке."""
|
||||
|
||||
if root is None:
|
||||
return []
|
||||
node_values = {"name": root['name'], "phone": root['phone']}
|
||||
return bst_list_all(root['left']) + [node_values] + bst_list_all(root['right'])
|
||||
58
MusinAA/task1/structures/HashTable.py
Normal file
58
MusinAA/task1/structures/HashTable.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
"""
|
||||
Хеш-таблица
|
||||
|
||||
Хранится как список buckets фиксированной длины,
|
||||
каждый элемент — голова связного списка (или None).
|
||||
"""
|
||||
|
||||
from task1.structures.LinkedList import *
|
||||
|
||||
def hash_fun(name: str, size: int) -> int:
|
||||
"""Принимает имя и возвращает индекс бакета для него."""
|
||||
if size <= 0:
|
||||
raise ValueError("size должен быть больше 0")
|
||||
|
||||
hashSum = 0
|
||||
n = size+1
|
||||
base = 1103 # ord('я')
|
||||
for letter in name:
|
||||
hashSum += ord(letter) * pow(base, n)
|
||||
n -= 1
|
||||
return int(hashSum) % size
|
||||
|
||||
def ht_insert(buckets: list, name: str, phone: str) -> list:
|
||||
"""Возвращает новый массив бакетов
|
||||
Вычисляет индекс, вызывает ll_insert для соответствующего бакета.
|
||||
Функция не меняет размер массива бакетов автоматически!"""
|
||||
if buckets == []:
|
||||
raise ValueError("Длинна buckets должна быть больше 0")
|
||||
|
||||
size = len(buckets)
|
||||
index = hash_fun(name, size)
|
||||
buckets[index] = ll_insert(buckets[index], name, phone)
|
||||
return buckets
|
||||
|
||||
def ht_delete(buckets: list, name: str) -> list:
|
||||
"""Возвращает новый массив бакетов без элемента с именем name"""
|
||||
if buckets == []:
|
||||
raise ValueError("Длинна buckets должна быть больше 0")
|
||||
|
||||
size = len(buckets)
|
||||
index = hash_fun(name, size)
|
||||
buckets[index] = ll_delete(buckets[index], name)
|
||||
return buckets
|
||||
|
||||
def ht_find(buckets: list, name: str) -> str:
|
||||
if buckets == []:
|
||||
raise ValueError("Длинна buckets должна быть больше 0")
|
||||
|
||||
size = len(buckets)
|
||||
index = hash_fun(name, size)
|
||||
return ll_find(buckets[index], name)
|
||||
|
||||
def ht_list_all(buckets):
|
||||
"""Собирает все записи из всех бакетов и сортирует"""
|
||||
allRecords = []
|
||||
for bucket in buckets:
|
||||
allRecords.extend(ll_list_all(bucket))
|
||||
return sorted(allRecords, key=lambda x: x[0])
|
||||
60
MusinAA/task1/structures/LinkedList.py
Normal file
60
MusinAA/task1/structures/LinkedList.py
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
"""
|
||||
Связный список (LinkedListPhoneBook)
|
||||
|
||||
Узел представляется словарём:
|
||||
{'name': 'Имя', 'phone': '123', 'next': None}.
|
||||
"""
|
||||
|
||||
|
||||
def ll_insert(head : dict|None, name: str, phone: str) -> dict:
|
||||
"""
|
||||
Проходит до конца (или сразу добавляет в конец) и возвращает новую
|
||||
голову (если вставка в начало) или изменяет список по ссылке.
|
||||
Удобнее возвращать новую голову, если вставка может быть в начало.
|
||||
"""
|
||||
|
||||
newNode = {'name': name, 'phone': phone, 'next': None}
|
||||
if head == None:
|
||||
return newNode
|
||||
|
||||
currentNode = head
|
||||
while currentNode['next'] != None:
|
||||
currentNode = currentNode['next']
|
||||
currentNode['next'] = newNode
|
||||
return head
|
||||
|
||||
def ll_find(head : dict|None, name: str) -> str|None:
|
||||
"""Ищет узел, возвращает телефон или None."""
|
||||
currentNode = head
|
||||
while currentNode != None:
|
||||
if currentNode['name'] == name:
|
||||
return currentNode['phone']
|
||||
currentNode = currentNode['next']
|
||||
return None
|
||||
|
||||
def ll_delete(head : dict|None, name: str) -> dict:
|
||||
"""Удаляет узел, возвращает новую голову."""
|
||||
if head == None:
|
||||
return None
|
||||
|
||||
if head['name'] == name:
|
||||
return head['next']
|
||||
|
||||
currentNode = head
|
||||
while currentNode['next'] != None:
|
||||
if currentNode['next']['name'] == name:
|
||||
currentNode['next'] = currentNode['next']['next']
|
||||
return head
|
||||
currentNode = currentNode['next']
|
||||
return head
|
||||
|
||||
def ll_list_all(head: dict|None) -> list:
|
||||
"""Cобирает все записи в список и сортирует.
|
||||
сортировка вынесена отдельно)."""
|
||||
records = []
|
||||
currentNode = head
|
||||
while currentNode != None:
|
||||
records.append((currentNode['name'], currentNode['phone']))
|
||||
currentNode = currentNode['next']
|
||||
records.sort(key=lambda item: item[0])
|
||||
return records
|
||||
0
MusinAA/task1/structures/__init__.py
Normal file
0
MusinAA/task1/structures/__init__.py
Normal file
Loading…
Reference in New Issue
Block a user