2026-05-14 00:57:12 +00:00
|
|
|
|
# phonebook.py
|
|
|
|
|
|
|
|
|
|
|
|
# Узел списка: {'n': имя, 'p': телефон, 'nxt': следующий}
|
|
|
|
|
|
def ll_insert(head, name, phone):
|
|
|
|
|
|
# обновление, если уже есть
|
|
|
|
|
|
curr = head
|
|
|
|
|
|
while curr is not None:
|
|
|
|
|
|
if curr['n'] == name:
|
|
|
|
|
|
curr['p'] = phone
|
|
|
|
|
|
return head
|
|
|
|
|
|
curr = curr['nxt']
|
|
|
|
|
|
# вставка в начало (новый узел становится головой)
|
|
|
|
|
|
new_node = {'n': name, 'p': phone, 'nxt': head}
|
|
|
|
|
|
return new_node
|
|
|
|
|
|
|
|
|
|
|
|
def ll_find(head, name):
|
|
|
|
|
|
curr = head
|
|
|
|
|
|
while curr is not None:
|
|
|
|
|
|
if curr['n'] == name:
|
|
|
|
|
|
return curr['p']
|
|
|
|
|
|
curr = curr['nxt']
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def ll_delete(head, name):
|
|
|
|
|
|
if head is None:
|
|
|
|
|
|
return None
|
|
|
|
|
|
if head['n'] == name:
|
|
|
|
|
|
return head['nxt']
|
|
|
|
|
|
prev = head
|
|
|
|
|
|
curr = head['nxt']
|
|
|
|
|
|
while curr is not None:
|
|
|
|
|
|
if curr['n'] == name:
|
|
|
|
|
|
prev['nxt'] = curr['nxt']
|
|
|
|
|
|
return head
|
|
|
|
|
|
prev = curr
|
|
|
|
|
|
curr = curr['nxt']
|
|
|
|
|
|
return head
|
|
|
|
|
|
|
|
|
|
|
|
def ll_list_all(head):
|
|
|
|
|
|
records = []
|
|
|
|
|
|
curr = head
|
|
|
|
|
|
while curr is not None:
|
|
|
|
|
|
records.append((curr['n'], curr['p']))
|
|
|
|
|
|
curr = curr['nxt']
|
|
|
|
|
|
records.sort(key=lambda x: x[0])
|
2026-05-14 00:59:11 +00:00
|
|
|
|
return records
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-05-14 01:00:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-05-14 00:59:11 +00:00
|
|
|
|
# хеш-функция – сумма ord(name) % size
|
|
|
|
|
|
def _hash(name, size):
|
|
|
|
|
|
h = 0
|
|
|
|
|
|
for ch in name:
|
|
|
|
|
|
h += ord(ch)
|
|
|
|
|
|
return h % size
|
|
|
|
|
|
|
|
|
|
|
|
SIZE = 13 # фиксированный размер таблицы
|
|
|
|
|
|
|
|
|
|
|
|
def ht_create():
|
|
|
|
|
|
return [None] * SIZE
|
|
|
|
|
|
|
|
|
|
|
|
def ht_insert(buckets, name, phone):
|
|
|
|
|
|
idx = _hash(name, len(buckets))
|
|
|
|
|
|
buckets[idx] = ll_insert(buckets[idx], name, phone)
|
|
|
|
|
|
return buckets
|
|
|
|
|
|
|
|
|
|
|
|
def ht_find(buckets, name):
|
|
|
|
|
|
idx = _hash(name, len(buckets))
|
|
|
|
|
|
return ll_find(buckets[idx], name)
|
|
|
|
|
|
|
|
|
|
|
|
def ht_delete(buckets, name):
|
|
|
|
|
|
idx = _hash(name, len(buckets))
|
|
|
|
|
|
buckets[idx] = ll_delete(buckets[idx], name)
|
|
|
|
|
|
return buckets
|
|
|
|
|
|
|
|
|
|
|
|
def ht_list_all(buckets):
|
|
|
|
|
|
all_records = []
|
|
|
|
|
|
for head in buckets:
|
|
|
|
|
|
curr = head
|
|
|
|
|
|
while curr:
|
|
|
|
|
|
all_records.append((curr['n'], curr['p']))
|
|
|
|
|
|
curr = curr['nxt']
|
|
|
|
|
|
all_records.sort(key=lambda x: x[0])
|
2026-05-14 01:00:11 +00:00
|
|
|
|
return all_records
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Узел дерева: {'n': имя, 'p': телефон, 'l': левый, 'r': правый}
|
|
|
|
|
|
def bst_create_node(name, phone):
|
|
|
|
|
|
return {'n': name, 'p': phone, 'l': None, 'r': None}
|
|
|
|
|
|
|
|
|
|
|
|
def bst_insert(root, name, phone):
|
|
|
|
|
|
if root is None:
|
|
|
|
|
|
return bst_create_node(name, phone)
|
|
|
|
|
|
# итеративная вставка (без рекурсии)
|
|
|
|
|
|
parent = None
|
|
|
|
|
|
cur = root
|
|
|
|
|
|
while cur:
|
|
|
|
|
|
parent = cur
|
|
|
|
|
|
if name == cur['n']:
|
|
|
|
|
|
cur['p'] = phone
|
|
|
|
|
|
return root
|
|
|
|
|
|
elif name < cur['n']:
|
|
|
|
|
|
cur = cur['l']
|
|
|
|
|
|
else:
|
|
|
|
|
|
cur = cur['r']
|
|
|
|
|
|
# вставляем как лист
|
|
|
|
|
|
if name < parent['n']:
|
|
|
|
|
|
parent['l'] = bst_create_node(name, phone)
|
|
|
|
|
|
else:
|
|
|
|
|
|
parent['r'] = bst_create_node(name, phone)
|
|
|
|
|
|
return root
|
|
|
|
|
|
|
|
|
|
|
|
def bst_find(root, name):
|
|
|
|
|
|
cur = root
|
|
|
|
|
|
while cur:
|
|
|
|
|
|
if name == cur['n']:
|
|
|
|
|
|
return cur['p']
|
|
|
|
|
|
elif name < cur['n']:
|
|
|
|
|
|
cur = cur['l']
|
|
|
|
|
|
else:
|
|
|
|
|
|
cur = cur['r']
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def _bst_min(node):
|
|
|
|
|
|
while node['l']:
|
|
|
|
|
|
node = node['l']
|
|
|
|
|
|
return node
|
|
|
|
|
|
|
|
|
|
|
|
def bst_delete(root, name):
|
|
|
|
|
|
if root is None:
|
|
|
|
|
|
return None
|
|
|
|
|
|
# поиск узла и родителя
|
|
|
|
|
|
parent = None
|
|
|
|
|
|
cur = root
|
|
|
|
|
|
while cur and cur['n'] != name:
|
|
|
|
|
|
parent = cur
|
|
|
|
|
|
if name < cur['n']:
|
|
|
|
|
|
cur = cur['l']
|
|
|
|
|
|
else:
|
|
|
|
|
|
cur = cur['r']
|
|
|
|
|
|
if cur is None:
|
|
|
|
|
|
return root
|
|
|
|
|
|
# случай 0 или 1 ребёнок
|
|
|
|
|
|
if cur['l'] is None or cur['r'] is None:
|
|
|
|
|
|
child = cur['l'] if cur['l'] else cur['r']
|
|
|
|
|
|
if parent is None:
|
|
|
|
|
|
return child
|
|
|
|
|
|
if parent['l'] == cur:
|
|
|
|
|
|
parent['l'] = child
|
|
|
|
|
|
else:
|
|
|
|
|
|
parent['r'] = child
|
|
|
|
|
|
else:
|
|
|
|
|
|
# два ребёнка – ищем inorder-преемника
|
|
|
|
|
|
succ_parent = cur
|
|
|
|
|
|
succ = cur['r']
|
|
|
|
|
|
while succ['l']:
|
|
|
|
|
|
succ_parent = succ
|
|
|
|
|
|
succ = succ['l']
|
|
|
|
|
|
cur['n'], cur['p'] = succ['n'], succ['p']
|
|
|
|
|
|
if succ_parent['l'] == succ:
|
|
|
|
|
|
succ_parent['l'] = succ['r']
|
|
|
|
|
|
else:
|
|
|
|
|
|
succ_parent['r'] = succ['r']
|
|
|
|
|
|
return root
|
|
|
|
|
|
|
|
|
|
|
|
def bst_list_all(root):
|
|
|
|
|
|
result = []
|
|
|
|
|
|
def inorder(node):
|
|
|
|
|
|
if node:
|
|
|
|
|
|
inorder(node['l'])
|
|
|
|
|
|
result.append((node['n'], node['p']))
|
|
|
|
|
|
inorder(node['r'])
|
|
|
|
|
|
inorder(root)
|
|
|
|
|
|
return result
|