119 lines
4.3 KiB
Python
119 lines
4.3 KiB
Python
|
|
"""
|
||
|
|
plot_results.py - строит столбчатые диаграммы по итогам экспериментов.
|
||
|
|
"""
|
||
|
|
import csv
|
||
|
|
import os
|
||
|
|
import matplotlib.pyplot as plt
|
||
|
|
import numpy as np
|
||
|
|
|
||
|
|
CSV = os.path.join("docs", "data", "results.csv")
|
||
|
|
PLOTS_DIR = os.path.join("docs", "data", "plots")
|
||
|
|
os.makedirs(PLOTS_DIR, exist_ok=True)
|
||
|
|
|
||
|
|
|
||
|
|
def load_means():
|
||
|
|
"""Возвращает dict[(structure, mode, op)] = (mean, N)."""
|
||
|
|
means = {}
|
||
|
|
with open(CSV, encoding="utf-8") as f:
|
||
|
|
rows = list(csv.reader(f))
|
||
|
|
# ищем секцию "--- СРЕДНИЕ ---"
|
||
|
|
start = None
|
||
|
|
for i, row in enumerate(rows):
|
||
|
|
if row and row[0] == "--- СРЕДНИЕ ---":
|
||
|
|
start = i + 2 # пропустить заголовок секции
|
||
|
|
break
|
||
|
|
for row in rows[start:]:
|
||
|
|
if not row:
|
||
|
|
continue
|
||
|
|
structure, mode, op, n, mean, _trials = row
|
||
|
|
means[(structure, mode, op)] = (float(mean), int(n))
|
||
|
|
return means
|
||
|
|
|
||
|
|
|
||
|
|
def plot_grouped(means, op, fname, title):
|
||
|
|
"""Сгруппированные столбцы: для каждой структуры - два столбца (shuffled / sorted)."""
|
||
|
|
structures = ["LinkedList", "HashTable", "BST"]
|
||
|
|
modes = ["shuffled", "sorted"]
|
||
|
|
x = np.arange(len(structures))
|
||
|
|
width = 0.36
|
||
|
|
|
||
|
|
fig, ax = plt.subplots(figsize=(8, 5))
|
||
|
|
|
||
|
|
for i, mode in enumerate(modes):
|
||
|
|
vals_ms = []
|
||
|
|
labels = []
|
||
|
|
for s in structures:
|
||
|
|
mean, n = means[(s, mode, op)]
|
||
|
|
vals_ms.append(mean * 1000)
|
||
|
|
labels.append(f"N={n}")
|
||
|
|
bars = ax.bar(x + (i - 0.5) * width, vals_ms, width,
|
||
|
|
label=mode, alpha=0.85)
|
||
|
|
for bar, lab in zip(bars, labels):
|
||
|
|
h = bar.get_height()
|
||
|
|
ax.text(bar.get_x() + bar.get_width() / 2, h,
|
||
|
|
f"{h:.2f}\n{lab}", ha="center", va="bottom", fontsize=8)
|
||
|
|
|
||
|
|
ax.set_xticks(x)
|
||
|
|
ax.set_xticklabels(structures)
|
||
|
|
ax.set_ylabel("Время, мс (среднее по 5 запускам)")
|
||
|
|
ax.set_title(title)
|
||
|
|
ax.set_yscale("log")
|
||
|
|
ax.legend(title="порядок входных данных")
|
||
|
|
ax.grid(axis="y", linestyle="--", alpha=0.4)
|
||
|
|
plt.tight_layout()
|
||
|
|
out = os.path.join(PLOTS_DIR, fname)
|
||
|
|
plt.savefig(out, dpi=130)
|
||
|
|
plt.close()
|
||
|
|
print("saved:", out)
|
||
|
|
|
||
|
|
|
||
|
|
def plot_bst_degradation(means, fname):
|
||
|
|
"""Отдельный график: BST shuffled vs sorted - даже при меньшем N
|
||
|
|
отсортированные данные дают намного большее время."""
|
||
|
|
ops = ["insert", "find", "delete"]
|
||
|
|
shuffled = [means[("BST", "shuffled", op)][0] * 1000 for op in ops]
|
||
|
|
sorted_ = [means[("BST", "sorted", op)][0] * 1000 for op in ops]
|
||
|
|
n_shuf = means[("BST", "shuffled", "insert")][1]
|
||
|
|
n_sort = means[("BST", "sorted", "insert")][1]
|
||
|
|
|
||
|
|
x = np.arange(len(ops))
|
||
|
|
width = 0.36
|
||
|
|
fig, ax = plt.subplots(figsize=(7, 4.5))
|
||
|
|
ax.bar(x - width/2, shuffled, width, label=f"shuffled (N={n_shuf})")
|
||
|
|
ax.bar(x + width/2, sorted_, width, label=f"sorted (N={n_sort})")
|
||
|
|
for i, v in enumerate(shuffled):
|
||
|
|
ax.text(i - width/2, v, f"{v:.2f}", ha="center", va="bottom", fontsize=9)
|
||
|
|
for i, v in enumerate(sorted_):
|
||
|
|
ax.text(i + width/2, v, f"{v:.2f}", ha="center", va="bottom", fontsize=9)
|
||
|
|
|
||
|
|
ax.set_xticks(x); ax.set_xticklabels(ops)
|
||
|
|
ax.set_ylabel("Время, мс")
|
||
|
|
ax.set_title("BST: деградация на отсортированных данных\n"
|
||
|
|
"(N для sorted в 5 раз меньше, но время больше)")
|
||
|
|
ax.set_yscale("log")
|
||
|
|
ax.legend()
|
||
|
|
ax.grid(axis="y", linestyle="--", alpha=0.4)
|
||
|
|
plt.tight_layout()
|
||
|
|
out = os.path.join(PLOTS_DIR, fname)
|
||
|
|
plt.savefig(out, dpi=130)
|
||
|
|
plt.close()
|
||
|
|
print("saved:", out)
|
||
|
|
|
||
|
|
|
||
|
|
def main():
|
||
|
|
means = load_means()
|
||
|
|
plot_grouped(means, "insert",
|
||
|
|
"insert_compare.png",
|
||
|
|
"Вставка всех записей (лог. шкала)")
|
||
|
|
plot_grouped(means, "find",
|
||
|
|
"find_compare.png",
|
||
|
|
"Поиск 110 ключей (лог. шкала)")
|
||
|
|
plot_grouped(means, "delete",
|
||
|
|
"delete_compare.png",
|
||
|
|
"Удаление 50 записей (лог. шкала)")
|
||
|
|
plot_bst_degradation(means, "bst_degradation.png")
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|