2026-rff_mp/ProninVV/aufgabe-1-data-structures/aufg1.py

276 lines
8.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# LInkedList (Node = List = {'name': 'Имя', 'phone': '123', 'next': None}) имена уникальные (id)
def ll_insert(head, name, phone):
""" проходит до конца (или сразу добавляет в конец) и возвращает новую голову
(если вставка в начало) или изменяет список по ссылке. Удобнее возвращать новую
голову, если вставка может быть в начало """
new_node = {'name': name, 'phone': phone, 'next': None}
# если списка не было
if head is None:
return new_node
# # вставка в начало O(1)
# new_node = {'name': name, 'phone': phone, 'next': head}
# return new_node
# вставка в конец O(n)
current = head
while current['next'] is not None:
# проверка существования данного идентификатора (обновляем запись)
if current['name'] == name:
current['phone'] = phone
return head
current = current['next']
# проверка на id
if current['name'] == name:
current['phone'] = phone
else: current['next'] = new_node
return head
def ll_find(head, name):
""" ищет узел, возвращает телефон или None """
current = head
while current is not None:
if current['name'] == name:
return current['phone']
current = current['next']
return None
def ll_delete(head, name):
""" удаляет узел, возвращает новую голову """
if head is None:
return None
# Удаление первого
if head['name'] == name:
new_head = head['next']
head['next'] = None
return new_head
# Если не первый
current = head
while current['next'] is not None:
if current['next']['name'] == name:
target = current['next']
current['next'] = target['next']
target['next'] = None
return head
current = current['next']
return head
def ll_list_all(head):
""" собирает все записи в список и сортирует (сортировка вынесена отдельно) """
length = ll_Lenght(head)
new_list = [None]*length
current = head
for i in range(length):
new_list[i] = (current['name'], current['phone'])
current = current['next']
sorten(new_list)
return new_list
# вспомогательные функции--------------------------------
def ll_Lenght(head):
# длина связного списка
counter = 0
curr = head
while curr:
counter += 1
curr = curr['next']
return counter
def sorten(arr):
n = len(arr)
for i in range(n):
for j in range(0, n - i - 1):
if arr[j][0] > arr[j + 1][0]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
# -----------------------------------------------------------
# linklist = None
# linklist = ll_insert(linklist, 'Sjora', '123')
# linklist = ll_insert(linklist, 'Vlad', '0000')
# linklist = ll_insert(linklist, 'Dima', '228')
# print(linklist)
# print(ll_find(linklist, 'Vlad'))
# print(ll_delete(linklist, 'Dima'))
# print(ll_list_all(linklist))
# HashTable (Хранится как список buckets фиксированной длины, каждый элемент — голова связного списка (или None))
def hash_table(size):
return [None]*size
def hash_func(name, buckets_count):
h = 0
for char in name:
h += ord(char)
return h % buckets_count
def ht_insert(buckets, name, phone):
""" вычисляет индекс, вызывает ll_insert для соответствующего бакета """
if buckets is None:
return
index = hash_func(name, len(buckets))
buckets[index] = ll_insert(buckets[index], name, phone)
def ht_find(buckets, name):
""" """
idx = hash_func(name, len(buckets))
return ll_find(buckets[idx], name)
def ht_delete(buckets, name):
idx = hash_func(name, len(buckets))
buckets[idx] = ll_delete(buckets[idx], name)
def ht_list_all(buckets):
""" собирает все записи из всех бакетов и сортирует """
total_count = 0
for head in buckets:
total_count += ll_Lenght(head)
full_data = [None]*total_count
k = 0
for head in buckets:
curr = head
while curr:
full_data[k] = (curr['name'], curr['phone'])
k += 1
curr = curr['next']
sorten(full_data)
return full_data
# Hash_table1 = hash_table(3)
# ht_insert(Hash_table1, 'Vlad', '000')
# ht_insert(Hash_table1, 'Dima', '111')
# ht_insert(Hash_table1, 'Sjora', '222')
# print(ht_list_all(Hash_table1))
# Двоичное дерево поиска : Узел — словарь: {'name': 'Имя', 'phone': '123', 'left': None, 'right': None}
def bst_insert(root, name, phone):
""" рекурсивно или итеративно вставляет, возвращает новый корень (если корень меняется) """
new_node = {'name': name, 'phone': phone, 'left': None, 'right': None}
# если дерева нет
if root is None:
return new_node
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):
""" поиск """
if root is None:
return None
if root['name'] == name:
return root['phone']
elif name < root['name']:
return bst_find(root['left'], name)
elif name > root['name']:
return bst_find(root['right'], name)
def bst_delete(root, name):
""" удаление, возвращает новый корень """
if root is None:
return None
# спускаемся к нужному узлу (аналогично поиску)
elif 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 and root['right'] is None:
# обрываем связь
return None
# если только один наследник
elif root['left'] is None != root['right'] is None:
return root['left'] or root['right']
# два наследника (поиск минимального поддерева в правой ветке)
successor = root['right']
while successor['left'] is not None:
successor = root['left']
root['name'] = successor['name']
root['phone'] = successor['phone']
# Удаляем дубликат преемника в правом поддереве
root['right'] = bst_delete(root['right'], successor['name'])
return root
def bst_list_all(root, result=None):
""" центрированный обход (рекурсивно собирает записи в отсортированном порядке) """
if result is None:
result = []
# сначала спускаемся по левой стороне вниз, затем идем вверх и вправо
if root is not None:
bst_list_all(root['left'], result)
result.append((root['name'], root['phone']))
bst_list_all(root['right'], result)
return result
# derevo = None
# derevo = bst_insert(derevo, 'Vlad', '000')
# derevo = bst_insert(derevo, 'Dima', '111')
# derevo = bst_insert(derevo, 'Sjora', '222')
# derevo = bst_insert(derevo, 'weid', '0')
# # print(derevo)
# # derevo = bst_delete(derevo, 'Vlad')
# print(bst_list_all(derevo))