106 lines
5.1 KiB
Python
106 lines
5.1 KiB
Python
|
|
import time
|
|||
|
|
import random
|
|||
|
|
import csv
|
|||
|
|
import structures as st # Предполагается, что у вас есть модуль с реализациями структур данных
|
|||
|
|
|
|||
|
|
N=10000
|
|||
|
|
REPEATS=5
|
|||
|
|
|
|||
|
|
# Генерируем список записей из N элементов, каждая запись - имя и телефон
|
|||
|
|
def generate_records(N):
|
|||
|
|
records = [
|
|||
|
|
(f"User_{i:05d}", f"+7{random.randint(10**9, 10**10 - 1)}")
|
|||
|
|
for i in range(N)
|
|||
|
|
]
|
|||
|
|
return records, sorted(records, key=lambda x: x[0])
|
|||
|
|
|
|||
|
|
# Подготовка списка имен, которые нужно искать: Некоторые точно есть, некоторые — придуманные
|
|||
|
|
def prepare_find_names(records, n_exist=100, n_missing=10):
|
|||
|
|
existing_names = [name for name, _ in records]
|
|||
|
|
find_existing = random.sample(existing_names, n_exist) # Имена, которые есть
|
|||
|
|
find_missing = [f"None_{i}" for i in range(n_missing)] # Не существующие имена
|
|||
|
|
return find_existing + find_missing
|
|||
|
|
|
|||
|
|
# Подготовка списка имен для удаления
|
|||
|
|
def prepare_delete_names(records, n_delete=50):
|
|||
|
|
existing_names = [name for name, _ in records]
|
|||
|
|
return random.sample(existing_names, n_delete) # случайные имена для удаления
|
|||
|
|
|
|||
|
|
# Обертка для измерения времени выполнения функции
|
|||
|
|
def measure_time(func, *args):
|
|||
|
|
start = time.perf_counter() # Точное время начала
|
|||
|
|
result = func(*args) # Вызов функции
|
|||
|
|
return result, time.perf_counter() - start # Возвращаем результат и время выполнения
|
|||
|
|
|
|||
|
|
# Определение структур данных и соответствующих функций для операций
|
|||
|
|
STRUCTURES = [
|
|||
|
|
("LinkedList", st.ll_insert, st.ll_find, st.ll_delete),
|
|||
|
|
("HashTable", st.ht_insert, st.ht_find, st.ht_delete),
|
|||
|
|
("BST", st.bst_insert, st.bst_find, st.bst_delete),
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# Функция для построения структуры данных из записей и измерения времени вставки
|
|||
|
|
def build_and_measure(build_func, records, init_val):
|
|||
|
|
head = init_val
|
|||
|
|
for name, phone in records:
|
|||
|
|
head = build_func(head, name, phone) # Построение структуре поэлементно
|
|||
|
|
return head # Возвращает финальную структуру
|
|||
|
|
|
|||
|
|
# Основная функция для запуска одного эксперимента
|
|||
|
|
def run_one_experiment(records_shuffled, records_sorted, find_names, delete_names):
|
|||
|
|
results = []
|
|||
|
|
for mode, recs in [("shuffled", records_shuffled), ("sorted", records_sorted)]:
|
|||
|
|
for name, build_fn, find_fn, delete_fn in STRUCTURES:
|
|||
|
|
init_val = None if name in ("LinkedList", "BST") else [None] * 10007
|
|||
|
|
head, t_insert = measure_time(build_and_measure, build_fn, recs, init_val)
|
|||
|
|
|
|||
|
|
# Создаем функции для поиска и удаления с фиксированными параметрами
|
|||
|
|
def search_fn():
|
|||
|
|
return [find_fn(head, n) for n in find_names]
|
|||
|
|
|
|||
|
|
def delete_fn_wrapper():
|
|||
|
|
return [delete_fn(head, n) for n in delete_names]
|
|||
|
|
|
|||
|
|
t_find = measure_time(search_fn)[1]
|
|||
|
|
t_delete = measure_time(delete_fn_wrapper)[1]
|
|||
|
|
|
|||
|
|
results += [
|
|||
|
|
[name, mode, "insert", t_insert],
|
|||
|
|
[name, mode, "find", t_find],
|
|||
|
|
[name, mode, "delete", t_delete],
|
|||
|
|
]
|
|||
|
|
return results
|
|||
|
|
|
|||
|
|
# Генерация исходных данных
|
|||
|
|
records_shuffled, records_sorted = generate_records(N)
|
|||
|
|
|
|||
|
|
# Подготовка списков имен для поиска и удаления
|
|||
|
|
find_names = prepare_find_names(records_sorted)
|
|||
|
|
delete_names = prepare_delete_names(records_sorted)
|
|||
|
|
|
|||
|
|
# Заголовки результатов
|
|||
|
|
results = [["Запуск", "Структура", "Режим", "Операция", "Время (сек)"]]
|
|||
|
|
|
|||
|
|
# Проведение серии запусков
|
|||
|
|
for run in range(1, REPEATS+1):
|
|||
|
|
print(f"Запуск эксперимента: {run}")
|
|||
|
|
one_run_results = run_one_experiment(records_shuffled, records_sorted, find_names, delete_names)
|
|||
|
|
for struct, mode, op, t in one_run_results:
|
|||
|
|
results.append([run, struct, mode, op, t]) # Добавляем результаты каждого запуска
|
|||
|
|
|
|||
|
|
# Подсчет средних значений по результатам
|
|||
|
|
groups = {}
|
|||
|
|
for row in results[1:]:
|
|||
|
|
key = tuple(row[1:4]) # Ключ — название структуры, режим, тип операции
|
|||
|
|
groups.setdefault(key, []).append(row[4]) # Собираем времена для среднего
|
|||
|
|
|
|||
|
|
for key, times in groups.items():
|
|||
|
|
avg_time = sum(times)/len(times)
|
|||
|
|
results.append(["average"] + list(key) + [avg_time]) # Средний результат
|
|||
|
|
|
|||
|
|
# Запись итоговых данных в CSV файл
|
|||
|
|
with open("results.csv", "w", newline="", encoding="utf-8") as f:
|
|||
|
|
writer = csv.writer(f)
|
|||
|
|
writer.writerows(results)
|
|||
|
|
|
|||
|
|
print("Результаты сохранены")
|