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()