2026-rff_mp/ShapovalovKA/docs/data/1Task/t1_1.py

212 lines
8.1 KiB
Python
Raw Normal View History

2026-05-25 08:58:51 +00:00
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()