forked from UNN/2026-rff_mp
129 lines
4.7 KiB
Python
129 lines
4.7 KiB
Python
|
|
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")
|