import random import time import csv # ---------- Реализация связного списка ---------- 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 # ---------- Измерения для массива ---------- def array_insert_measure(records, sorted_flag=False): # Вставка записей в начало массива. Возвращает время. arr = [] start = time.perf_counter() if sorted_flag: # records уже отсортированы for item in records: arr.insert(0, item) else: for item in records: arr.insert(0, item) end = time.perf_counter() return end - start def array_find_measure(records, test_names): # Поиск в массиве: линейный перебор. start = time.perf_counter() for name in test_names: for rec in records: if rec[0] == name: break end = time.perf_counter() return end - start def array_delete_measure(records, delete_names): # Удаление из массива через создание нового списка (как в оригинале). times = [] for name in delete_names: start = time.perf_counter() records = [rec for rec in records if rec[0] != name] end = time.perf_counter() times.append(end - start) return sum(times) / len(times) if times else 0 # ---------- Измерения для связного списка ---------- def linked_insert_measure(records, sorted_flag=False): # Вставка записей в начало связного списка. Возвращает время. head = None start = time.perf_counter() # Если sorted_flag == True, records уже отсортированы, но для связного списка # вставка в начало всегда O(1), порядок не влияет на время. for name, phone in records: head = ll_insert_begin(head, name, phone) end = time.perf_counter() return end - start def linked_find_measure(head, test_names): # Поиск в связном списке. start = time.perf_counter() for name in test_names: ll_find(head, name) end = time.perf_counter() return end - start def linked_delete_measure(head, delete_names): # Удаление из связного списка. times = [] for name in delete_names: start = time.perf_counter() head = ll_delete(head, name) end = time.perf_counter() times.append(end - start) return sum(times) / len(times) if times else 0 # ---------- Основная функция эксперимента ---------- def main(): N = 10000 # Генерация тестовых данных records = [] for i in range(N): name = f"User_{i:05d}" phone = f"8{random.randint(9000000000, 9999999999)}" records.append((name, phone)) 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) # Результаты будем собирать в список списков results = [["Структура", "Режим", "Операция", "Время (сек)"]] # ----- Массив ----- # Вставка (случайный порядок) arr_time_shuffled = 0.0 arr_time_sorted = 0.0 for _ in range(5): arr_time_shuffled += array_insert_measure(records_shuffled, sorted_flag=False) arr_time_sorted += array_insert_measure(records_sorted, sorted_flag=True) results.append(["Array", "случайный", "вставка (в начало)", arr_time_shuffled / 5]) results.append(["Array", "отсортированный", "вставка (в начало)", arr_time_sorted / 5]) # Поиск find_time = 0.0 for _ in range(5): find_time += array_find_measure(records, test_names) results.append(["Array", "любой", "поиск 110 записей", find_time / 5]) # Удаление del_time = 0.0 for _ in range(5): del_time += array_delete_measure(records.copy(), delete_names) results.append(["Array", "любой", "удаление 50 записей (среднее)", del_time / 5]) # ----- Связный список ----- # Вставка ll_time_shuffled = 0.0 ll_time_sorted = 0.0 for _ in range(5): ll_time_shuffled += linked_insert_measure(records_shuffled) ll_time_sorted += linked_insert_measure(records_sorted) results.append(["Linked list", "случайный", "вставка (в начало)", ll_time_shuffled / 5]) results.append(["Linked list", "отсортированный", "вставка (в начало)", ll_time_sorted / 5]) # Поиск (предварительно строим список) head = None for name, phone in records: head = ll_insert_begin(head, name, phone) find_time_ll = 0.0 for _ in range(5): find_time_ll += linked_find_measure(head, test_names) results.append(["Linked list", "любой", "поиск 110 записей", find_time_ll / 5]) # Удаление (копируем список для каждого замера) del_time_ll = 0.0 for _ in range(5): # Строим новую копию списка h = None for name, phone in records: h = ll_insert_begin(h, name, phone) del_time_ll += linked_delete_measure(h, delete_names) results.append(["Linked list", "любой", "удаление 50 записей (среднее)", del_time_ll / 5]) # ----- Вывод результатов в единый столбец ----- print("\nРезультаты экспериментов (время в секундах):\n") # Определяем максимальную ширину первого столбца для красивого выравнивания col_widths = [max(len(str(row[i])) for row in results) for i in range(4)] for row in results: print(f"{row[0]:<{col_widths[0]}} {row[1]:<{col_widths[1]}} " f"{row[2]:<{col_widths[2]}} {row[3]:<{col_widths[3]}}") # ----- Запись результатов в CSV-файл ----- with open('results.csv', 'w', newline='', encoding='utf-8-sig') as csvfile: writer = csv.writer(csvfile, delimiter = ';') writer.writerows(results) print("\nРезультаты сохранены в файл 'results.csv'.") if __name__ == "__main__": main()