2026-rff_mp/ivanchenkoam/laba1.txt

330 lines
10 KiB
Plaintext
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.

import time
import csv
import random
import sys
from typing import List, Tuple, Optional, Any, Dict
#лимит рекурсии
sys.setrecursionlimit(20000)
def ll_insert(head: Optional[Dict], name: str, phone: str) -> Dict:
"""Вставка в конец связного списка"""
new_node = {'name': name, 'phone': phone, 'next': None}
if head is None:
return new_node
current = head
while current['next'] is not None:
# Обновляем, если уже есть
if current['name'] == name:
current['phone'] = phone
return head
current = current['next']
if current['name'] == name:
current['phone'] = phone
else:
current['next'] = new_node
return head
def ll_find(head: Optional[Dict], name: str) -> Optional[str]:
"""Поиск в связном списке"""
current = head
while current is not None:
if current['name'] == name:
return current['phone']
current = current['next']
return None
def ll_delete(head: Optional[Dict], name: str) -> Optional[Dict]:
"""Удаление из связного списка"""
if head is None:
return None
if head['name'] == name:
return head['next']
current = head
while current['next'] is not None:
if current['next']['name'] == name:
current['next'] = current['next']['next']
return head
current = current['next']
return head
def ll_list_all(head: Optional[Dict]) -> List[Tuple[str, str]]:
"""Сбор всех записей из связного списка с сортировкой"""
records = []
current = head
while current is not None:
records.append((current['name'], current['phone']))
current = current['next']
def hash_function(name: str, size: int) -> int:
"""Простая хеш-функция"""
return sum(ord(c) for c in name) % size
def ht_create(size: int = 1000) -> List[Optional[Dict]]:
"""Создание хеш-таблицы"""
return [None] * size
def ht_insert(buckets: List[Optional[Dict]], name: str, phone: str) -> None:
"""Вставка в хеш-таблицу"""
index = hash_function(name, len(buckets))
buckets[index] = ll_insert(buckets[index], name, phone)
def ht_find(buckets: List[Optional[Dict]], name: str) -> Optional[str]:
"""Поиск в хеш-таблице"""
index = hash_function(name, len(buckets))
return ll_find(buckets[index], name)
def ht_delete(buckets: List[Optional[Dict]], name: str) -> None:
"""Удаление из хеш-таблицы"""
index = hash_function(name, len(buckets))
buckets[index] = ll_delete(buckets[index], name)
def ht_list_all(buckets: List[Optional[Dict]]) -> List[Tuple[str, str]]:
"""Сбор всех записей из хеш-таблицы с сортировкой"""
records = []
for head in buckets:
current = head
while current is not None:
records.append((current['name'], current['phone']))
current = current['next']
records.sort(key=lambda x: x[0])
return records
def bst_insert(root: Optional[Dict], name: str, phone: str) -> Dict:
"""Вставка в BST (итеративная)"""
new_node = {'name': name, 'phone': phone, 'left': None, 'right': None}
if root is None:
return new_node
current = root
while True:
if name < current['name']:
if current['left'] is None:
current['left'] = new_node
break
else:
current = current['left']
elif name > current['name']:
if current['right'] is None:
current['right'] = new_node
break
else:
current = current['right']
else:
# Обновляем существующую запись
current['phone'] = phone
break
return root
def bst_find(root: Optional[Dict], name: str) -> Optional[str]:
"""Поиск в BST (итеративный)"""
current = root
while current is not None:
if name == current['name']:
return current['phone']
elif name < current['name']:
current = current['left']
else:
current = current['right']
return None
def bst_min_node(node: Dict) -> Dict:
"""Поиск узла с минимальным значением"""
current = node
while current['left'] is not None:
current = current['left']
return current
def bst_delete(root: Optional[Dict], name: str) -> Optional[Dict]:
"""Удаление из BST (итеративная версия)"""
if root is None:
return None
# Поиск узла для удаления и его родителя
parent = None
current = root
while current is not None and current['name'] != name:
parent = current
if name < current['name']:
current = current['left']
else:
current = current['right']
if current is None:
return root
# Случай 1: узел не имеет детей
if current['left'] is None and current['right'] is None:
if parent is None:
return None
if parent['left'] == current:
parent['left'] = None
else:
parent['right'] = None
return root
# Случай 2: узел имеет одного ребёнка
if current['left'] is None:
child = current['right']
elif current['right'] is None:
child = current['left']
else:
# Случай 3: узел имеет двух детей
# Находим минимальный узел в правом поддереве
successor_parent = current
successor = current['right']
while successor['left'] is not None:
successor_parent = successor
successor = successor['left']
# Копируем данные из successor в current
current['name'] = successor['name']
current['phone'] = successor['phone']
# Удаляем successor
if successor_parent['left'] == successor:
successor_parent['left'] = successor['right']
else:
successor_parent['right'] = successor['right']
return root
# Присоединяем ребёнка к родителю
if parent is None:
return child
if parent['left'] == current:
parent['left'] = child
else:
parent['right'] = child
return root
def bst_inorder(root: Optional[Dict], records: List[Tuple[str, str]]) -> None:
"""Центрированный обход BST (рекурсивный)"""
if root is not None:
bst_inorder(root['left'], records)
records.append((root['name'], root['phone']))
bst_inorder(root['right'], records)
def bst_list_all(root: Optional[Dict]) -> List[Tuple[str, str]]:
"""Сбор всех записей из BST (уже отсортированы)"""
records = []
bst_inorder(root, records)
return records
records.sort(key=lambda x: x[0])
return records
def generate_records(n: int) -> List[Tuple[str, str]]:
"""Генерация записей"""
records = [(f"User_{i:05d}", f"+7-999-{i:07d}") for i in range(n)]
return records
def measure_insertion(structure_type: str, data: List[Tuple[str, str]],
ht_size: int = 1000) -> float:
"""Замер времени вставки"""
start = time.perf_counter()
if structure_type == "LinkedList":
head = None
for name, phone in data:
head = ll_insert(head, name, phone)
elif structure_type == "HashTable":
buckets = ht_create(ht_size)
for name, phone in data:
ht_insert(buckets, name, phone)
elif structure_type == "BST":
root = None
for name, phone in data:
root = bst_insert(root, name, phone)
end = time.perf_counter()
return end - start
def measure_find(structure_type: str, data: List[Tuple[str, str]],
existing_names: List[str], missing_names: List[str],
ht_size: int = 1000) -> Tuple[float, Any]:
"""Замер времени поиска (возвращает время и структуру для удаления)"""
# Сначала создаём структуру
if structure_type == "LinkedList":
head = None
for name, phone in data:
head = ll_insert(head, name, phone)
start = time.perf_counter()
for name in existing_names + missing_names:
ll_find(head, name)
end = time.perf_counter()
return end - start, head
elif structure_type == "HashTable":
buckets = ht_create(ht_size)
for name, phone in data:
ht_insert(buckets, name, phone)
start = time.perf_counter()
for name in existing_names + missing_names:
ht_find(buckets, name)
end = time.perf_counter()
return end - start, buckets
elif structure_type == "BST":
root = None
for name, phone in data:
root = bst_insert(root, name, phone)
start = time.perf_counter()
for name in existing_names + missing_names:
bst_find(root, name)
end = time.perf_counter()
return end - start, root
def measure_delete(structure_type: str, structure: Any,
names_to_delete: List[str]) -> float:
"""Замер времени удаления"""
start = time.perf_counter()
if structure_type == "LinkedList":
head = structure
for name in names_to_delete:
head = ll_delete(head, name)
elif structure_type == "HashTable":
buckets = structure
for name in names_to_delete:
ht_delete(buckets, name)
elif structure_type == "BST":
root = structure
for name in names_to_delete:
root = bst_delete(root, name)
end = time.perf_counter()
return end - start