2026-rff_mp/ShapovalovKA/docs/data/1Task/t1_2.py
2026-05-25 11:58:51 +03:00

185 lines
7.2 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.

import random
import time
import csv
import os
# --------------------- Реализация связного списка (взята из t1_1) ---------------------
def ll_insert_begin(head, name, phone):
# Вставка узла в начало списка. Возвращает новую голову.
new_node = {'name': name, 'phone': phone, 'next': head}
return new_node
def ll_find(head, name):
# Поиск телефона по имени. Возвращает phone или None.
current = head
while current:
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:
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
# --------------------- Реализация хеш-таблицы ---------------------
class HashTable:
def __init__(self, size=2000):
self.size = size
self.buckets = [None] * size # каждый bucket — голова связного списка
def _hash(self, name):
# Простая хеш-функция: сумма кодов символов по модулю размера.
return sum(ord(ch) for ch in name) % self.size
def insert(self, name, phone):
index = self._hash(name)
# Вставляем в начало связного списка в данном bucket'е
self.buckets[index] = ll_insert_begin(self.buckets[index], name, phone)
def find(self, name):
index = self._hash(name)
return ll_find(self.buckets[index], name)
def delete(self, name):
index = self._hash(name)
self.buckets[index] = ll_delete(self.buckets[index], name)
def list_all(self):
# Собирает все записи из всех bucket'ов и сортирует по имени.
all_records = []
for head in self.buckets:
current = head
while current:
all_records.append((current['name'], current['phone']))
current = current['next']
all_records.sort(key=lambda x: x[0])
return all_records
# --------------------- Функции измерений ---------------------
def generate_data(N=10000):
records = []
for i in range(N):
name = f"User_{i:05d}"
phone = f"8{random.randint(9000000000, 9999999999)}"
records.append((name, phone))
return records
def measure_insert(records, sort_order='random'):
# Измеряет время вставки в хеш-таблицу.
# sort_order: 'random' или 'sorted' — порядок передаваемых записей.
ht = HashTable(size=2000)
start = time.perf_counter()
for name, phone in records:
ht.insert(name, phone)
end = time.perf_counter()
return end - start
def measure_find(records, test_names):
# Поиск 110 записей в уже заполненной хеш-таблице.
ht = HashTable(size=2000)
for name, phone in records:
ht.insert(name, phone)
start = time.perf_counter()
for name in test_names:
ht.find(name)
end = time.perf_counter()
return end - start
def measure_delete(records, delete_names):
# Удаление 50 записей из хеш-таблицы (среднее время одного удаления).
times = []
for name in delete_names:
ht = HashTable(size=2000)
for n, p in records:
ht.insert(n, p)
start = time.perf_counter()
ht.delete(name)
end = time.perf_counter()
times.append(end - start)
return sum(times) / len(times)
# --------------------- Основная функция ---------------------
def main():
N = 10000
records = generate_data(N)
# Перемешанные и отсортированные копии
records_shuffled = records.copy()
random.shuffle(records_shuffled)
records_sorted = sorted(records, key=lambda x: x[0])
# Имена для поиска (100 существующих + 10 несуществующих)
existing_names = random.sample([rec[0] for rec in records], 100)
non_existing = [f"None_{i}" for i in range(10)]
test_names = existing_names + non_existing
# Имена для удаления (50 случайных)
delete_names = random.sample([rec[0] for rec in records], 50)
# Замеры (по 5 повторений)
insert_shuffled_avg = 0.0
insert_sorted_avg = 0.0
find_avg = 0.0
delete_avg = 0.0
repeats = 5
for _ in range(repeats):
insert_shuffled_avg += measure_insert(records_shuffled, 'random')
insert_sorted_avg += measure_insert(records_sorted, 'sorted')
find_avg += measure_find(records, test_names)
delete_avg += measure_delete(records, delete_names)
insert_shuffled_avg /= repeats
insert_sorted_avg /= repeats
find_avg /= repeats
delete_avg /= repeats
# Подготовка строк для CSV
new_rows = [
["Hash table", "случайный", "вставка (в начало)", insert_shuffled_avg],
["Hash table", "отсортированный", "вставка (в начало)", insert_sorted_avg],
["Hash table", "любой", "поиск 110 записей", find_avg],
["Hash table", "любой", "удаление 50 записей (среднее)", delete_avg]
]
# Определяем имя CSV-файла (там же, где и t1_1.py)
csv_filename = "results.csv"
file_exists = os.path.isfile(csv_filename)
# Запись в CSV (добавление)
with open(csv_filename, 'a', newline='', encoding='utf-8-sig') as f:
writer = csv.writer(f, delimiter=';')
# Если файл только что создан, сначала запишем заголовок
if not file_exists:
writer.writerow(["Структура", "Режим", "Операция", "Время (сек)"])
writer.writerows(new_rows)
print("Результаты для хеш-таблицы добавлены в", csv_filename)
print(f"Среднее время вставки (случ. порядок): {insert_shuffled_avg:.6f} сек")
print(f"Среднее время вставки (отсорт.): {insert_sorted_avg:.6f} сек")
print(f"Среднее время поиска 110 записей: {find_avg:.6f} сек")
print(f"Среднее время удаления 50 записей: {delete_avg:.6f} сек")
if __name__ == "__main__":
main()