import csv import os try: import matplotlib.pyplot as plt import matplotlib.patches as mpatches HAS_MPL = True except ImportError: HAS_MPL = False print("⚠️ matplotlib не установлен. Установите: pip install matplotlib") print(" Графики будут пропущены, таблица результатов выведена в терминал.\n") CSV_PATH = os.path.join(os.path.dirname(__file__), 'results.csv') PLOTS_DIR = os.path.dirname(__file__) def load_results(path): data = {} with open(path, newline='', encoding='utf-8') as f: reader = csv.reader(f) header = next(reader) for row in reader: struct, mode, op = row[0], row[1], row[2] mean = float(row[3]) data[(struct, mode, op)] = mean return data STRUCTS = ["LinkedList", "HashTable", "BST"] MODES = ["случайный", "сортированный"] OPS = ["insert", "find", "delete"] COLORS = {"LinkedList": "#4E9AF1", "HashTable": "#F4845F", "BST": "#6BCB77"} def plot_by_operation(data): fig, axes = plt.subplots(1, 3, figsize=(15, 5)) fig.suptitle("Сравнение структур данных\n(телефонный справочник, N=10 000)", fontsize=14, fontweight='bold') for ax, op in zip(axes, OPS): x_labels = [] values = [] colors = [] for mode in MODES: for struct in STRUCTS: key = (struct, mode, op) val = data.get(key, 0) x_labels.append(f"{struct}\n({mode[:4]})") values.append(val) colors.append(COLORS[struct]) bars = ax.bar(range(len(values)), values, color=colors, edgecolor='white', linewidth=0.8) ax.set_xticks(range(len(x_labels))) ax.set_xticklabels(x_labels, fontsize=8, rotation=15, ha='right') ax.set_ylabel("Время (с)", fontsize=9) ax.set_title(f"Операция: {op}", fontweight='bold') ax.grid(axis='y', alpha=0.3) for bar, val in zip(bars, values): ax.text(bar.get_x() + bar.get_width() / 2, bar.get_height() + max(values) * 0.01, f"{val:.4f}", ha='center', va='bottom', fontsize=7) patches = [mpatches.Patch(color=c, label=s) for s, c in COLORS.items()] fig.legend(handles=patches, loc='lower center', ncol=3, bbox_to_anchor=(0.5, -0.05)) plt.tight_layout() out_path = os.path.join(PLOTS_DIR, 'comparison_by_operation.png') plt.savefig(out_path, dpi=150, bbox_inches='tight') print(f"✅ График сохранён: {out_path}") plt.show() def plot_sorted_vs_random(data): fig, axes = plt.subplots(1, 3, figsize=(14, 5)) fig.suptitle("Влияние порядка данных на время операций", fontsize=13, fontweight='bold') for ax, struct in zip(axes, STRUCTS): rand_vals = [data.get((struct, "случайный", op), 0) for op in OPS] sort_vals = [data.get((struct, "сортированный", op), 0) for op in OPS] x = range(len(OPS)) w = 0.35 bars1 = ax.bar([i - w/2 for i in x], rand_vals, width=w, label="случайный", color="#4E9AF1", edgecolor='white') bars2 = ax.bar([i + w/2 for i in x], sort_vals, width=w, label="сортированный", color="#F4845F", edgecolor='white') ax.set_xticks(list(x)) ax.set_xticklabels(OPS) ax.set_title(struct, fontweight='bold') ax.set_ylabel("Время (с)", fontsize=9) ax.legend(fontsize=8) ax.grid(axis='y', alpha=0.3) plt.tight_layout() out_path = os.path.join(PLOTS_DIR, 'sorted_vs_random.png') plt.savefig(out_path, dpi=150, bbox_inches='tight') print(f"✅ График сохранён: {out_path}") plt.show() def print_table(data): print(f"\n{'Структура':<12} {'Режим':<16} {'Операция':<10} {'Время (с)':<12}") print("-" * 52) for (struct, mode, op), mean in sorted(data.items()): print(f"{struct:<12} {mode:<16} {op:<10} {mean:.6f}") if __name__ == "__main__": if not os.path.exists(CSV_PATH): print(f"❌ Файл результатов не найден: {CSV_PATH}") print(" Сначала запустите: python benchmark.py") exit(1) data = load_results(CSV_PATH) print_table(data) if HAS_MPL: plot_by_operation(data) plot_sorted_vs_random(data) else: print("\n💡 Установите matplotlib для графиков:") print(" pip install matplotlib")