diff --git a/BorisovMI/lab_1/docs/data/structures.py b/BorisovMI/lab_1/docs/data/structures.py index db7981c..ea514c1 100644 --- a/BorisovMI/lab_1/docs/data/structures.py +++ b/BorisovMI/lab_1/docs/data/structures.py @@ -5,7 +5,7 @@ import os import matplotlib.pyplot as plt import numpy as np import sys - +sys.setrecursionlimit(20000) # Связный список def ll_insert(head, name, phone): @@ -177,7 +177,7 @@ def bst_list_all(root): inorder_traversal(root) return records - # Генерация тесотовых данных + # Генерация тестовых данных def generate_records(count=10000): @@ -228,7 +228,6 @@ def measure_insertion(structure_name, records): return times, filled_structure - def measure_search(structure_name, structure, search_names): times = [] @@ -249,7 +248,6 @@ def measure_search(structure_name, structure, search_names): return times - def measure_deletion(structure_name, original_structure, delete_names): times = [] @@ -286,4 +284,194 @@ def measure_deletion(structure_name, original_structure, delete_names): end = time.perf_counter() times.append(end - start) - return times \ No newline at end of file + return times + +# Основная часть + +def run_experiment(): + + current_dir = os.path.dirname(__name__) + docs_dir = os.path.dirname(current_dir) + csv_file = os.path.join(docs_dir, "experiment_results.csv") + + print("=" * 70) + print("ЭКСПЕРИМЕНТАЛЬНОЕ СРАВНЕНИЕ СТРУКТУР ДАННЫХ") + print("Телефонный справочник - 10000 записей") + print("=" * 70) + print(f"\nРезультаты будут сохранены в: {csv_file}") + + print("\n1. Генерация тестовых данных...") + shuffled_records, sorted_records = generate_records(10000) + print(f" Сгенерировано 10000 записей") + + existing_names = [shuffled_records[i][0] for i in random.sample(range(10000), 100)] + nonexisting_names = [f"NotExist_{i}" for i in range(10)] + search_names = existing_names + nonexisting_names + delete_names = [shuffled_records[i][0] for i in random.sample(range(10000), 50)] + + results = [["Структура", "Режим", "Операция", + "Замер1(с)", "Замер2(с)", "Замер3(с)", "Замер4(с)", "Замер5(с)", + "Среднее(с)"]] + + for mode_name, records in [("случайный", shuffled_records), + ("отсортированный", sorted_records)]: + + print(f"\n2. Тестирование режима: {mode_name}") + print("-" * 50) + + for struct_name in ["linked_list", "hash_table", "bst"]: + print(f"\n {struct_name.upper()}:") + + print(" Вставка 10000 записей...") + insert_times, filled_struct = measure_insertion(struct_name, records) + avg_insert = sum(insert_times) / 5 + print(f" Время: {avg_insert:.4f} сек (среднее)") + + print(" Поиск 110 записей...") + search_times = measure_search(struct_name, filled_struct, search_names) + avg_search = sum(search_times) / 5 + print(f" Время: {avg_search:.4f} сек (среднее)") + + print(" Удаление 50 записей...") + delete_times = measure_deletion(struct_name, filled_struct, delete_names) + avg_delete = sum(delete_times) / 5 + print(f" Время: {avg_delete:.4f} сек (среднее)") + + results.append([struct_name, mode_name, "вставка"] + insert_times + [avg_insert]) + results.append([struct_name, mode_name, "поиск"] + search_times + [avg_search]) + results.append([struct_name, mode_name, "удаление"] + delete_times + [avg_delete]) + + print("\n3. Сохранение результатов...") + with open(csv_file, "w", newline="", encoding="utf-8") as f: + writer = csv.writer(f) + writer.writerows(results) + print(f" Результаты сохранены в: {csv_file}") + + print("\n" + "=" * 70) + print("СВОДНАЯ ТАБЛИЦА РЕЗУЛЬТАТОВ") + print("=" * 70) + print(f"{'Структура':<15} {'Режим':<12} {'Операция':<10} {'Среднее время (сек)':<20}") + print("-" * 70) + + for row in results[1:]: + struct, mode, op, t1, t2, t3, t4, t5, avg = row + print(f"{struct:<15} {mode:<12} {op:<10} {avg:<20.6f}") + + return results, docs_dir + +# Графики + +def create_graphs(results, docs_dir): + + print("\n4. Построение графиков...") + + data = {} + for row in results[1:]: + struct = row[0] + mode = row[1] + op = row[2] + avg = row[8] + + if struct not in data: + data[struct] = {} + if mode not in data[struct]: + data[struct][mode] = {} + data[struct][mode][op] = avg + + + struct_labels = { + 'linked_list': 'LinkedList', + 'hash_table': 'HashTable', + 'bst': 'BST' + } + + + colors = { + 'linked_list': '#3498db', + 'hash_table': '#2ecc71', + 'bst': '#e74c3c' + } + + + fig, axes = plt.subplots(1, 3, figsize=(15, 6)) + fig.suptitle('Сравнение производительности структур данных', fontsize=16, fontweight='bold') + + operations = ['вставка', 'поиск', 'удаление'] + operation_titles = ['Вставка\n(10000 записей)', 'Поиск\n(110 запросов)', 'Удаление\n(50 записей)'] + modes = ['случайный', 'отсортированный'] + mode_labels = ['Случайный', 'Отсортированный'] + + for idx, (op, op_title) in enumerate(zip(operations, operation_titles)): + ax = axes[idx] + + # Позиции для групп столбцов + x = np.arange(len(modes)) # [0, 1] + width = 0.25 # ширина одного столбца + multiplier = 0 + + for struct in ['linked_list', 'hash_table', 'bst']: + values = [data[struct][mode][op] for mode in modes] + offset = width * multiplier + bars = ax.bar(x + offset, values, width, + label=struct_labels[struct], + color=colors[struct], + edgecolor='black', linewidth=0.5) + + + for bar, val in zip(bars, values): + if val < 0.01: + ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + val*0.05, + f'{val:.5f}', ha='center', va='bottom', fontsize=8, rotation=0) + else: + ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + val*0.02, + f'{val:.4f}', ha='center', va='bottom', fontsize=8, rotation=0) + + multiplier += 1 + + + ax.set_title(op_title, fontsize=12, fontweight='bold') + ax.set_ylabel('Время (секунды)', fontsize=10) + ax.set_xlabel('Режим данных', fontsize=10) + ax.set_xticks(x + width) + ax.set_xticklabels(mode_labels) + ax.legend(loc='upper left', fontsize=8) + ax.grid(True, alpha=0.3, axis='y') + + + all_values = [data[s][m][op] for s in ['linked_list', 'hash_table', 'bst'] for m in modes] + if max(all_values) / min(all_values) > 100: + ax.set_yscale('log') + ax.set_ylabel('Время (секунды) - логарифмическая шкала', fontsize=9) + + plt.tight_layout() + graph_path = os.path.join(docs_dir, "performance_graphs.png") + plt.savefig(graph_path, dpi=150, bbox_inches='tight') + plt.close() + print(f" Графики сохранены в: {graph_path}") + + return graph_path + + + +if __name__ == "__main__": + + results, docs_dir = run_experiment() + + + try: + graph_file = create_graphs(results, docs_dir) + + print("\n" + "=" * 70) + print("ЭКСПЕРИМЕНТ ЗАВЕРШЕН УСПЕШНО!") + print("=" * 70) + print("\nСОЗДАННЫЕ ФАЙЛЫ:") + print(f" Данные: {os.path.join(docs_dir, 'experiment_results.csv')}") + print(f" Графики: {graph_file}") + + except Exception as e: + print(f"\nОшибка при построении графиков: {e}") + print(" Убедитесь, что установлен matplotlib: pip install matplotlib") + print("\n" + "=" * 70) + print("ЭКСПЕРИМЕНТ ЗАВЕРШЕН (без графиков)") + print("=" * 70) + print(f"\nCSV файл сохранен: {os.path.join(docs_dir, 'experiment_results.csv')}") \ No newline at end of file diff --git a/BorisovMI/lab_1/docs/experiment_results.csv b/BorisovMI/lab_1/docs/experiment_results.csv new file mode 100644 index 0000000..b3a472b --- /dev/null +++ b/BorisovMI/lab_1/docs/experiment_results.csv @@ -0,0 +1,19 @@ +Структура,Режим,Операция,Замер1(с),Замер2(с),Замер3(с),Замер4(с),Замер5(с),Среднее(с) +linked_list,случайный,вставка,11.072574299992993,12.38099840003997,12.155311000009533,12.81002289999742,13.201067199988756,12.323994760005736 +linked_list,случайный,поиск,0.1209169999929145,0.13400630000978708,0.1302103999769315,0.12179599999217317,0.13267739996081218,0.12792141998652368 +linked_list,случайный,удаление,0.05278969998471439,0.05019940005149692,0.05289009999250993,0.0488043999648653,0.061356800026260316,0.05320808000396937 +hash_table,случайный,вставка,0.694432099990081,0.7192347000236623,0.7134853000170551,0.6891152000171132,0.6973775000078604,0.7027289600111544 +hash_table,случайный,поиск,0.006584499962627888,0.004749000014271587,0.004359900020062923,0.006477299961261451,0.006112299975939095,0.005656599986832589 +hash_table,случайный,удаление,0.004070399969350547,0.004140400036703795,0.003542299964465201,0.0032371999695897102,0.0030583000043407083,0.0036097199888899924 +bst,случайный,вставка,0.08137199998600408,0.08989329996984452,0.08159760001581162,0.07841239997651428,0.1001471999916248,0.08628449998795987 +bst,случайный,поиск,0.0006561999907717109,0.00043180002830922604,0.00042429997120052576,0.0004227000172249973,0.00043509999522939324,0.0004740200005471706 +bst,случайный,удаление,0.19723930000327528,0.166880399978254,0.147482400003355,0.18100009998306632,0.16498840000713244,0.1715181199950166 +linked_list,отсортированный,вставка,12.294058899977244,11.597062399960123,11.59195000003092,11.623520500026643,11.401553199975751,11.701628999994137 +linked_list,отсортированный,поиск,0.10066379996715114,0.0991929000010714,0.09696789999725297,0.09909789997618645,0.09873830003198236,0.09893215999472886 +linked_list,отсортированный,удаление,0.05669830000260845,0.048193000024184585,0.05076910002389923,0.04920080001465976,0.05905079998774454,0.05278240001061931 +hash_table,отсортированный,вставка,0.5518350999918766,0.5407364999991842,0.5291212999727577,0.5373308000271209,0.529426000022795,0.5376899400027468 +hash_table,отсортированный,поиск,0.005108800018206239,0.004848999960813671,0.004103399987798184,0.0038874000310897827,0.005848900007549673,0.00475950000109151 +hash_table,отсортированный,удаление,0.0037329999613575637,0.003185699984896928,0.0028516000020317733,0.0030229000258259475,0.0037879000301472843,0.003316220000851899 +bst,отсортированный,вставка,32.23637629998848,33.77348939998774,33.518200399994384,33.78866110002855,33.55791890004184,33.3749292200082 +bst,отсортированный,поиск,0.1479294000309892,0.1305704999831505,0.13548930000979453,0.1314462999580428,0.130273999995552,0.1351418999955058 +bst,отсортированный,удаление,0.1574716999894008,0.16461069998331368,0.15460990002611652,0.15385339997010306,0.15677610004786402,0.15746436000335962 diff --git a/BorisovMI/lab_1/docs/performance_graphs.png b/BorisovMI/lab_1/docs/performance_graphs.png new file mode 100644 index 0000000..8cfee3f Binary files /dev/null and b/BorisovMI/lab_1/docs/performance_graphs.png differ