This commit is contained in:
Andrey 2026-09-05 01:36:33 +03:00
parent e6b4e51999
commit 5d337d933b
8 changed files with 2278946 additions and 132 deletions

View File

@ -1,109 +1,109 @@
Structure,Mode,Operation,Time (sec)
LinkedList,random,insert (trial 1),3.415125
LinkedList,random,find (trial 1),0.035397
LinkedList,random,delete (trial 1),0.017692
LinkedList,random,insert (trial 2),3.534952
LinkedList,random,find (trial 2),0.038819
LinkedList,random,delete (trial 2),0.021675
LinkedList,random,insert (trial 3),3.493529
LinkedList,random,find (trial 3),0.036592
LinkedList,random,delete (trial 3),0.018221
LinkedList,random,insert (trial 4),3.340745
LinkedList,random,find (trial 4),0.036098
LinkedList,random,delete (trial 4),0.017576
LinkedList,random,insert (trial 5),3.369741
LinkedList,random,find (trial 5),0.035302
LinkedList,random,delete (trial 5),0.017674
LinkedList,random,Insert (avg),3.430818
LinkedList,random,Find (avg),0.036442
LinkedList,random,Delete (avg),0.018568
LinkedList,sorted,insert (trial 1),3.118200
LinkedList,sorted,find (trial 1),0.037116
LinkedList,sorted,delete (trial 1),0.019387
LinkedList,sorted,insert (trial 2),3.338498
LinkedList,sorted,find (trial 2),0.036500
LinkedList,sorted,delete (trial 2),0.019001
LinkedList,sorted,insert (trial 3),3.136906
LinkedList,sorted,find (trial 3),0.037498
LinkedList,sorted,delete (trial 3),0.019219
LinkedList,sorted,insert (trial 4),3.253578
LinkedList,sorted,find (trial 4),0.036434
LinkedList,sorted,delete (trial 4),0.019333
LinkedList,sorted,insert (trial 5),3.207896
LinkedList,sorted,find (trial 5),0.038585
LinkedList,sorted,delete (trial 5),0.020473
LinkedList,sorted,Insert (avg),3.211016
LinkedList,sorted,Find (avg),0.037227
LinkedList,sorted,Delete (avg),0.019482
HashTable,random,insert (trial 1),0.010124
HashTable,random,find (trial 1),0.000093
HashTable,random,delete (trial 1),0.000052
HashTable,random,insert (trial 2),0.010397
HashTable,random,find (trial 2),0.000086
HashTable,random,delete (trial 2),0.000048
HashTable,random,insert (trial 3),0.009352
HashTable,random,find (trial 3),0.000081
HashTable,random,delete (trial 3),0.000046
HashTable,random,insert (trial 4),0.009326
HashTable,random,find (trial 4),0.000080
HashTable,random,delete (trial 4),0.000046
HashTable,random,insert (trial 5),0.010205
HashTable,random,find (trial 5),0.000081
HashTable,random,delete (trial 5),0.000046
HashTable,random,Insert (avg),0.009881
HashTable,random,Find (avg),0.000084
HashTable,random,Delete (avg),0.000048
HashTable,sorted,insert (trial 1),0.008975
LinkedList,random,insert (trial 1),3.492299
LinkedList,random,find (trial 1),0.037285
LinkedList,random,delete (trial 1),0.017788
LinkedList,random,insert (trial 2),3.626929
LinkedList,random,find (trial 2),0.037489
LinkedList,random,delete (trial 2),0.017875
LinkedList,random,insert (trial 3),3.520048
LinkedList,random,find (trial 3),0.038240
LinkedList,random,delete (trial 3),0.017604
LinkedList,random,insert (trial 4),3.506699
LinkedList,random,find (trial 4),0.038922
LinkedList,random,delete (trial 4),0.018784
LinkedList,random,insert (trial 5),3.556780
LinkedList,random,find (trial 5),0.038981
LinkedList,random,delete (trial 5),0.018246
LinkedList,random,Insert (avg),3.540551
LinkedList,random,Find (avg),0.038183
LinkedList,random,Delete (avg),0.018059
LinkedList,sorted,insert (trial 1),3.346370
LinkedList,sorted,find (trial 1),0.040201
LinkedList,sorted,delete (trial 1),0.020495
LinkedList,sorted,insert (trial 2),3.314037
LinkedList,sorted,find (trial 2),0.038854
LinkedList,sorted,delete (trial 2),0.019935
LinkedList,sorted,insert (trial 3),3.354769
LinkedList,sorted,find (trial 3),0.039805
LinkedList,sorted,delete (trial 3),0.020464
LinkedList,sorted,insert (trial 4),3.406509
LinkedList,sorted,find (trial 4),0.039368
LinkedList,sorted,delete (trial 4),0.020180
LinkedList,sorted,insert (trial 5),3.403112
LinkedList,sorted,find (trial 5),0.039473
LinkedList,sorted,delete (trial 5),0.020447
LinkedList,sorted,Insert (avg),3.364960
LinkedList,sorted,Find (avg),0.039540
LinkedList,sorted,Delete (avg),0.020304
HashTable,random,insert (trial 1),0.009849
HashTable,random,find (trial 1),0.000086
HashTable,random,delete (trial 1),0.000048
HashTable,random,insert (trial 2),0.009472
HashTable,random,find (trial 2),0.000083
HashTable,random,delete (trial 2),0.000044
HashTable,random,insert (trial 3),0.009662
HashTable,random,find (trial 3),0.000082
HashTable,random,delete (trial 3),0.000044
HashTable,random,insert (trial 4),0.009410
HashTable,random,find (trial 4),0.000082
HashTable,random,delete (trial 4),0.000044
HashTable,random,insert (trial 5),0.009140
HashTable,random,find (trial 5),0.000083
HashTable,random,delete (trial 5),0.000044
HashTable,random,Insert (avg),0.009507
HashTable,random,Find (avg),0.000083
HashTable,random,Delete (avg),0.000045
HashTable,sorted,insert (trial 1),0.009291
HashTable,sorted,find (trial 1),0.000087
HashTable,sorted,delete (trial 1),0.000050
HashTable,sorted,insert (trial 2),0.009137
HashTable,sorted,find (trial 2),0.000086
HashTable,sorted,delete (trial 2),0.000050
HashTable,sorted,insert (trial 3),0.009460
HashTable,sorted,find (trial 3),0.000086
HashTable,sorted,delete (trial 3),0.000049
HashTable,sorted,insert (trial 4),0.008977
HashTable,sorted,find (trial 4),0.000085
HashTable,sorted,delete (trial 1),0.000047
HashTable,sorted,insert (trial 2),0.009102
HashTable,sorted,find (trial 2),0.000100
HashTable,sorted,delete (trial 2),0.000090
HashTable,sorted,insert (trial 3),0.009200
HashTable,sorted,find (trial 3),0.000087
HashTable,sorted,delete (trial 3),0.000048
HashTable,sorted,insert (trial 4),0.009909
HashTable,sorted,find (trial 4),0.000089
HashTable,sorted,delete (trial 4),0.000049
HashTable,sorted,insert (trial 5),0.009416
HashTable,sorted,find (trial 5),0.000094
HashTable,sorted,delete (trial 5),0.000053
HashTable,sorted,Insert (avg),0.009193
HashTable,sorted,Find (avg),0.000087
HashTable,sorted,Delete (avg),0.000050
BST,random,insert (trial 1),0.031499
BST,random,find (trial 1),0.000274
BST,random,delete (trial 1),0.000153
BST,random,insert (trial 2),0.031806
BST,random,find (trial 2),0.000286
BST,random,delete (trial 2),0.000157
BST,random,insert (trial 3),0.031514
BST,random,find (trial 3),0.000267
BST,random,delete (trial 3),0.000150
BST,random,insert (trial 4),0.031758
BST,random,find (trial 4),0.000260
BST,random,delete (trial 4),0.000144
BST,random,insert (trial 5),0.031923
BST,random,find (trial 5),0.000262
BST,random,delete (trial 5),0.000145
BST,random,Insert (avg),0.031700
BST,random,Find (avg),0.000270
BST,random,Delete (avg),0.000150
BST,sorted,insert (trial 1),14.135551
BST,sorted,find (trial 1),0.123919
BST,sorted,delete (trial 1),0.054104
BST,sorted,insert (trial 2),13.781539
BST,sorted,find (trial 2),0.126835
BST,sorted,delete (trial 2),0.055120
BST,sorted,insert (trial 3),15.010563
BST,sorted,find (trial 3),0.117841
BST,sorted,delete (trial 3),0.056871
BST,sorted,insert (trial 4),14.378650
BST,sorted,find (trial 4),0.113316
BST,sorted,delete (trial 4),0.054129
BST,sorted,insert (trial 5),14.285981
BST,sorted,find (trial 5),0.112919
BST,sorted,delete (trial 5),0.057369
BST,sorted,Insert (avg),14.318457
BST,sorted,Find (avg),0.118966
BST,sorted,Delete (avg),0.055519
HashTable,sorted,insert (trial 5),0.009171
HashTable,sorted,find (trial 5),0.000088
HashTable,sorted,delete (trial 5),0.000049
HashTable,sorted,Insert (avg),0.009335
HashTable,sorted,Find (avg),0.000090
HashTable,sorted,Delete (avg),0.000057
BST,random,insert (trial 1),0.034288
BST,random,find (trial 1),0.000271
BST,random,delete (trial 1),0.000156
BST,random,insert (trial 2),0.032324
BST,random,find (trial 2),0.000272
BST,random,delete (trial 2),0.000154
BST,random,insert (trial 3),0.101986
BST,random,find (trial 3),0.000264
BST,random,delete (trial 3),0.000151
BST,random,insert (trial 4),0.031992
BST,random,find (trial 4),0.000265
BST,random,delete (trial 4),0.000151
BST,random,insert (trial 5),0.032047
BST,random,find (trial 5),0.000261
BST,random,delete (trial 5),0.000150
BST,random,Insert (avg),0.046528
BST,random,Find (avg),0.000266
BST,random,Delete (avg),0.000152
BST,sorted,insert (trial 1),12.604559
BST,sorted,find (trial 1),0.105486
BST,sorted,delete (trial 1),0.052166
BST,sorted,insert (trial 2),12.359827
BST,sorted,find (trial 2),0.116147
BST,sorted,delete (trial 2),0.057597
BST,sorted,insert (trial 3),12.470136
BST,sorted,find (trial 3),0.109819
BST,sorted,delete (trial 3),0.052912
BST,sorted,insert (trial 4),12.437366
BST,sorted,find (trial 4),0.104483
BST,sorted,delete (trial 4),0.051517
BST,sorted,insert (trial 5),12.580773
BST,sorted,find (trial 5),0.109896
BST,sorted,delete (trial 5),0.056510
BST,sorted,Insert (avg),12.490532
BST,sorted,Find (avg),0.109166
BST,sorted,Delete (avg),0.054140

1 Structure Mode Operation Time (sec)
2 LinkedList random insert (trial 1) 3.415125 3.492299
3 LinkedList random find (trial 1) 0.035397 0.037285
4 LinkedList random delete (trial 1) 0.017692 0.017788
5 LinkedList random insert (trial 2) 3.534952 3.626929
6 LinkedList random find (trial 2) 0.038819 0.037489
7 LinkedList random delete (trial 2) 0.021675 0.017875
8 LinkedList random insert (trial 3) 3.493529 3.520048
9 LinkedList random find (trial 3) 0.036592 0.038240
10 LinkedList random delete (trial 3) 0.018221 0.017604
11 LinkedList random insert (trial 4) 3.340745 3.506699
12 LinkedList random find (trial 4) 0.036098 0.038922
13 LinkedList random delete (trial 4) 0.017576 0.018784
14 LinkedList random insert (trial 5) 3.369741 3.556780
15 LinkedList random find (trial 5) 0.035302 0.038981
16 LinkedList random delete (trial 5) 0.017674 0.018246
17 LinkedList random Insert (avg) 3.430818 3.540551
18 LinkedList random Find (avg) 0.036442 0.038183
19 LinkedList random Delete (avg) 0.018568 0.018059
20 LinkedList sorted insert (trial 1) 3.118200 3.346370
21 LinkedList sorted find (trial 1) 0.037116 0.040201
22 LinkedList sorted delete (trial 1) 0.019387 0.020495
23 LinkedList sorted insert (trial 2) 3.338498 3.314037
24 LinkedList sorted find (trial 2) 0.036500 0.038854
25 LinkedList sorted delete (trial 2) 0.019001 0.019935
26 LinkedList sorted insert (trial 3) 3.136906 3.354769
27 LinkedList sorted find (trial 3) 0.037498 0.039805
28 LinkedList sorted delete (trial 3) 0.019219 0.020464
29 LinkedList sorted insert (trial 4) 3.253578 3.406509
30 LinkedList sorted find (trial 4) 0.036434 0.039368
31 LinkedList sorted delete (trial 4) 0.019333 0.020180
32 LinkedList sorted insert (trial 5) 3.207896 3.403112
33 LinkedList sorted find (trial 5) 0.038585 0.039473
34 LinkedList sorted delete (trial 5) 0.020473 0.020447
35 LinkedList sorted Insert (avg) 3.211016 3.364960
36 LinkedList sorted Find (avg) 0.037227 0.039540
37 LinkedList sorted Delete (avg) 0.019482 0.020304
38 HashTable random insert (trial 1) 0.010124 0.009849
39 HashTable random find (trial 1) 0.000093 0.000086
40 HashTable random delete (trial 1) 0.000052 0.000048
41 HashTable random insert (trial 2) 0.010397 0.009472
42 HashTable random find (trial 2) 0.000086 0.000083
43 HashTable random delete (trial 2) 0.000048 0.000044
44 HashTable random insert (trial 3) 0.009352 0.009662
45 HashTable random find (trial 3) 0.000081 0.000082
46 HashTable random delete (trial 3) 0.000046 0.000044
47 HashTable random insert (trial 4) 0.009326 0.009410
48 HashTable random find (trial 4) 0.000080 0.000082
49 HashTable random delete (trial 4) 0.000046 0.000044
50 HashTable random insert (trial 5) 0.010205 0.009140
51 HashTable random find (trial 5) 0.000081 0.000083
52 HashTable random delete (trial 5) 0.000046 0.000044
53 HashTable random Insert (avg) 0.009881 0.009507
54 HashTable random Find (avg) 0.000084 0.000083
55 HashTable random Delete (avg) 0.000048 0.000045
56 HashTable sorted insert (trial 1) 0.008975 0.009291
57 HashTable sorted find (trial 1) 0.000087
58 HashTable sorted delete (trial 1) 0.000050 0.000047
59 HashTable sorted insert (trial 2) 0.009137 0.009102
60 HashTable sorted find (trial 2) 0.000086 0.000100
61 HashTable sorted delete (trial 2) 0.000050 0.000090
62 HashTable sorted insert (trial 3) 0.009460 0.009200
63 HashTable sorted find (trial 3) 0.000086 0.000087
64 HashTable sorted delete (trial 3) 0.000049 0.000048
65 HashTable sorted insert (trial 4) 0.008977 0.009909
66 HashTable sorted find (trial 4) 0.000085 0.000089
67 HashTable sorted delete (trial 4) 0.000049
68 HashTable sorted insert (trial 5) 0.009416 0.009171
69 HashTable sorted find (trial 5) 0.000094 0.000088
70 HashTable sorted delete (trial 5) 0.000053 0.000049
71 HashTable sorted Insert (avg) 0.009193 0.009335
72 HashTable sorted Find (avg) 0.000087 0.000090
73 HashTable sorted Delete (avg) 0.000050 0.000057
74 BST random insert (trial 1) 0.031499 0.034288
75 BST random find (trial 1) 0.000274 0.000271
76 BST random delete (trial 1) 0.000153 0.000156
77 BST random insert (trial 2) 0.031806 0.032324
78 BST random find (trial 2) 0.000286 0.000272
79 BST random delete (trial 2) 0.000157 0.000154
80 BST random insert (trial 3) 0.031514 0.101986
81 BST random find (trial 3) 0.000267 0.000264
82 BST random delete (trial 3) 0.000150 0.000151
83 BST random insert (trial 4) 0.031758 0.031992
84 BST random find (trial 4) 0.000260 0.000265
85 BST random delete (trial 4) 0.000144 0.000151
86 BST random insert (trial 5) 0.031923 0.032047
87 BST random find (trial 5) 0.000262 0.000261
88 BST random delete (trial 5) 0.000145 0.000150
89 BST random Insert (avg) 0.031700 0.046528
90 BST random Find (avg) 0.000270 0.000266
91 BST random Delete (avg) 0.000150 0.000152
92 BST sorted insert (trial 1) 14.135551 12.604559
93 BST sorted find (trial 1) 0.123919 0.105486
94 BST sorted delete (trial 1) 0.054104 0.052166
95 BST sorted insert (trial 2) 13.781539 12.359827
96 BST sorted find (trial 2) 0.126835 0.116147
97 BST sorted delete (trial 2) 0.055120 0.057597
98 BST sorted insert (trial 3) 15.010563 12.470136
99 BST sorted find (trial 3) 0.117841 0.109819
100 BST sorted delete (trial 3) 0.056871 0.052912
101 BST sorted insert (trial 4) 14.378650 12.437366
102 BST sorted find (trial 4) 0.113316 0.104483
103 BST sorted delete (trial 4) 0.054129 0.051517
104 BST sorted insert (trial 5) 14.285981 12.580773
105 BST sorted find (trial 5) 0.112919 0.109896
106 BST sorted delete (trial 5) 0.057369 0.056510
107 BST sorted Insert (avg) 14.318457 12.490532
108 BST sorted Find (avg) 0.118966 0.109166
109 BST sorted Delete (avg) 0.055519 0.054140

Binary file not shown.

View File

@ -11,7 +11,6 @@ threading.stack_size(64*1024*1024)
def ll_insert(head, name, phone):
"""Добавляет запись или обновляет телефон, если имя уже существует. Возвращает новую голову списка."""
current = head
while current is not None:
if current["name"] == name:
@ -23,7 +22,6 @@ def ll_insert(head, name, phone):
return fresh_node
def ll_find(head, name):
"""Ищет узел по имени. Возвращает телефон или None."""
current = head
while current is not None:
if current["name"] == name:
@ -32,7 +30,6 @@ def ll_find(head, name):
return None
def ll_delete(head, name):
"""Удаляет узел по имени. Возвращает новую голову списка."""
current = head
previous = None
@ -49,7 +46,6 @@ def ll_delete(head, name):
return head
def ll_list_all(head):
"""Собирает все записи в список и сортирует их по имени."""
entries = []
current = head
while current is not None:
@ -60,26 +56,21 @@ def ll_list_all(head):
def ht_create(size=1000):
"""Создает пустую хеш-таблицу заданного размера."""
return [None] * size
def ht_insert(buckets, name, phone):
"""Вычисляет индекс бакета и вызывает ll_insert."""
bucket_idx = abs(hash(name)) % len(buckets)
buckets[bucket_idx] = ll_insert(buckets[bucket_idx], name, phone)
def ht_find(buckets, name):
"""Вычисляет индекс бакета и вызывает ll_find."""
bucket_idx = abs(hash(name)) % len(buckets)
return ll_find(buckets[bucket_idx], name)
def ht_delete(buckets, name):
"""Вычисляет индекс бакета и вызывает ll_delete."""
bucket_idx = abs(hash(name)) % len(buckets)
buckets[bucket_idx] = ll_delete(buckets[bucket_idx], name)
def ht_list_all(buckets):
"""Собирает записи из всех бакетов и сортирует их по имени."""
entries = []
for head_node in buckets:
current = head_node
@ -91,7 +82,6 @@ def ht_list_all(buckets):
def bst_insert(root, name, phone):
"""Рекурсивно вставляет узел или обновляет телефон."""
if root is None:
return {"name": name, "phone": phone, "left": None, "right": None}
@ -105,7 +95,6 @@ def bst_insert(root, name, phone):
return root
def bst_find(root, name):
"""Рекурсивный поиск по дереву."""
if root is None:
return None
@ -117,7 +106,6 @@ def bst_find(root, name):
return bst_find(root["right"], name)
def bst_delete(root, name):
"""Рекурсивное удаление узла из BST."""
if root is None:
return None
@ -142,7 +130,6 @@ def bst_delete(root, name):
return root
def bst_list_all(root):
"""Центрированный обход дерева для сбора записей."""
entries = []
def _inorder(node):
if node is not None:
@ -179,7 +166,7 @@ def perform_benchmark():
elif structure_kind == "HashTable": container = ht_create(size=1000)
elif structure_kind == "BST": container = None
# А. Вставка
#Вставка
timer_start = time.perf_counter()
if structure_kind == "LinkedList":
for name, phone in data_collection: container = ll_insert(container, name, phone)
@ -191,7 +178,7 @@ def perform_benchmark():
insertion_measurements.append(insert_elapsed)
output_rows.append([structure_kind, data_mode, f"insert (trial {trial_num})", f"{insert_elapsed:.6f}"])
# Б. Поиск
#Поиск
timer_start = time.perf_counter()
if structure_kind == "LinkedList":
for name in search_queries: ll_find(container, name)
@ -203,7 +190,7 @@ def perform_benchmark():
search_measurements.append(search_elapsed)
output_rows.append([structure_kind, data_mode, f"find (trial {trial_num})", f"{search_elapsed:.6f}"])
# В. Удаление
#Удаление
timer_start = time.perf_counter()
if structure_kind == "LinkedList":
for name in deletion_targets: container = ll_delete(container, name)
@ -234,23 +221,17 @@ def perform_benchmark():
execute_trial("BST", "random", shuffled_records)
execute_trial("BST", "sorted", ordered_records)
# Сохранение в CSV
with open("benchmark_output.csv", "w", newline="", encoding="utf-8") as csv_file:
csv_writer = csv.writer(csv_file)
csv_writer.writerows(output_rows)
print("\n[Success] All benchmarks completed! Results saved to 'benchmark_output.csv'.")
# ВЫЗЫВАЕМ ФУНКЦИЮ ДЛЯ СОЗДАНИЯ ГРАФИКОВ
generate_performance_charts(graph_entries)
def generate_performance_charts(plot_data):
"""
Создает графики производительности структур данных.
Args:
plot_data: список кортежей (structure, mode, avg_insert, avg_find, avg_delete)
"""
if not plot_data:
print("Нет данных для построения графиков")
return
@ -307,6 +288,5 @@ if __name__ == '__main__':
benchmark_thread.start()
benchmark_thread.join()
# Дополнительно: если графики не показались автоматически
# Можно вызвать функцию напрямую после завершения потока
print("\nПрограмма завершена. Проверьте файл 'performance_charts.png'")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

2278329
ivankinad/task2/Report2.rtf Normal file

File diff suppressed because it is too large Load Diff

484
ivankinad/task2/laba2.py Normal file
View File

@ -0,0 +1,484 @@
import time
import csv
from abc import ABC, abstractmethod
from collections import deque
from typing import List, Dict, Optional, Tuple
import heapq
#Модель лабиринта
class Cell:
def __init__(self, x: int, y: int):
self.x = x
self.y = y
self.is_wall = False
self.is_start = False
self.is_exit = False
self.weight = 1
def is_passable(self) -> bool:
return not self.is_wall
def __lt__(self, other):
return (self.x, self.y) < (other.x, other.y)
def __repr__(self):
return f"Cell({self.x}, {self.y})"
class Maze:
def __init__(self, width: int, height: int):
self.width = width
self.height = height
self.cells = [[Cell(x, y) for y in range(height)] for x in range(width)]
self.start: Optional[Cell] = None
self.exit: Optional[Cell] = None
def get_cell(self, x: int, y: int) -> Optional[Cell]:
if 0 <= x < self.width and 0 <= y < self.height:
return self.cells[x][y]
return None
def get_neighbors(self, cell: Cell) -> List[Cell]:
neighbors = []
directions = [(0, -1), (0, 1), (-1, 0), (1, 0)]
for dx, dy in directions:
nx, ny = cell.x + dx, cell.y + dy
neighbor = self.get_cell(nx, ny)
if neighbor and neighbor.is_passable():
neighbors.append(neighbor)
return neighbors
#Постройка лабиринта
class MazeBuilder(ABC):
@abstractmethod
def build_from_string_list(self, lines: List[str]) -> Maze:
pass
class TextMazeBuilder(MazeBuilder):
def build_from_string_list(self, lines: List[str]) -> Maze:
height = len(lines)
width = len(lines[0]) if height > 0 else 0
maze = Maze(width, height)
for y, line in enumerate(lines):
for x, char in enumerate(line):
cell = maze.get_cell(x, y)
if char == '#':
cell.is_wall = True
elif char == 'S':
cell.is_start = True
maze.start = cell
elif char == 'E':
cell.is_exit = True
maze.exit = cell
elif char == 'W':
cell.weight = 3
elif char == 'D':
cell.weight = 2
return maze
#Стратегии поиска пути
class PathFindingStrategy(ABC):
def __init__(self):
self.visited_count = 0
@abstractmethod
def find_path(self, maze: Maze, start: Cell, exit: Cell) -> List[Cell]:
pass
def _reconstruct_path(self, came_from: Dict, start: Cell, exit: Cell) -> List[Cell]:
if exit not in came_from:
return []
path = []
current = exit
while current != start:
path.append(current)
current = came_from[current]
path.append(start)
path.reverse()
return path
class BFSStrategy(PathFindingStrategy):
def find_path(self, maze: Maze, start: Cell, exit: Cell) -> List[Cell]:
self.visited_count = 0
queue = deque([start])
came_from = {start: None}
while queue:
current = queue.popleft()
self.visited_count += 1
if current == exit:
break
for neighbor in maze.get_neighbors(current):
if neighbor not in came_from:
queue.append(neighbor)
came_from[neighbor] = current
return self._reconstruct_path(came_from, start, exit)
class DFSStrategy(PathFindingStrategy):
def find_path(self, maze: Maze, start: Cell, exit: Cell) -> List[Cell]:
self.visited_count = 0
stack = [start]
came_from = {start: None}
while stack:
current = stack.pop()
self.visited_count += 1
if current == exit:
break
for neighbor in maze.get_neighbors(current):
if neighbor not in came_from:
stack.append(neighbor)
came_from[neighbor] = current
return self._reconstruct_path(came_from, start, exit)
class AStarStrategy(PathFindingStrategy):
def find_path(self, maze: Maze, start: Cell, exit: Cell) -> List[Cell]:
self.visited_count = 0
def heuristic(a: Cell, b: Cell) -> int:
return abs(a.x - b.x) + abs(a.y - b.y)
priority_queue = []
heapq.heappush(priority_queue, (0, start))
came_from = {start: None}
g_score = {start: 0}
while priority_queue:
_, current = heapq.heappop(priority_queue)
self.visited_count += 1
if current == exit:
break
for neighbor in maze.get_neighbors(current):
tentative_g_score = g_score[current] + neighbor.weight
if neighbor not in g_score or tentative_g_score < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = tentative_g_score
f_score = tentative_g_score + heuristic(neighbor, exit)
heapq.heappush(priority_queue, (f_score, neighbor))
return self._reconstruct_path(came_from, start, exit)
class DijkstraStrategy(PathFindingStrategy):
def find_path(self, maze: Maze, start: Cell, exit: Cell) -> List[Cell]:
self.visited_count = 0
priority_queue = []
heapq.heappush(priority_queue, (0, start))
came_from = {start: None}
g_score = {start: 0}
while priority_queue:
current_g, current = heapq.heappop(priority_queue)
self.visited_count += 1
if current == exit:
break
for neighbor in maze.get_neighbors(current):
tentative_g_score = g_score[current] + neighbor.weight
if neighbor not in g_score or tentative_g_score < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = tentative_g_score
heapq.heappush(priority_queue, (tentative_g_score, neighbor))
return self._reconstruct_path(came_from, start, exit)
#Оркестратор поиска
class SearchStats:
def __init__(self, time_ms: float, visited_cells: int, path_length: int):
self.time_ms = time_ms
self.visited_cells = visited_cells
self.path_length = path_length
def __str__(self):
return f"Time: {self.time_ms:.3f}ms | Visited: {self.visited_cells} | Path length: {self.path_length}"
class Observer(ABC):
@abstractmethod
def update(self, event: str):
pass
class MazeSolver:
def __init__(self, maze: Maze, strategy: PathFindingStrategy):
self.maze = maze
self.strategy = strategy
self.observers = []
def set_strategy(self, strategy: PathFindingStrategy):
self.strategy = strategy
def add_observer(self, observer: Observer):
self.observers.append(observer)
def _notify(self, event: str):
for observer in self.observers:
observer.update(event)
def solve(self) -> Tuple[List[Cell], SearchStats]:
self._notify("Search started")
start_time = time.perf_counter()
path = self.strategy.find_path(self.maze, self.maze.start, self.maze.exit)
end_time = time.perf_counter()
time_ms = (end_time - start_time) * 1000
stats = SearchStats(time_ms, self.strategy.visited_count, len(path))
self._notify("Search completed")
return path, stats
#Визуализация
class ConsoleView(Observer):
def update(self, event: str):
print(f"[Event] {event}")
def render(self, maze: Maze, path: List[Cell]):
path_set = set(path)
for y in range(maze.height):
row = ""
for x in range(maze.width):
cell = maze.get_cell(x, y)
if cell == maze.start:
row += "S"
elif cell == maze.exit:
row += "E"
elif cell in path_set:
row += "*"
elif cell.is_wall:
row += "#"
elif cell.weight == 3:
row += "W" # Болото
elif cell.weight == 2:
row += "D" # Песок
else:
row += "."
print(row)
#Экспериментальная часть
def create_test_mazes() -> Dict[str, Maze]:
builder = TextMazeBuilder()
mazes = {}
#Маленький лабиринт 10x10 с простым путём
small_maze = [
"S.........",
"#####.####",
"..........",
"####.#####",
"..........",
"#.#######.",
"..........",
"######.###",
"..........",
".........E"
]
mazes["Small (10x10)"] = builder.build_from_string_list(small_maze)
#Пустой лабиринт 50x50
empty_maze = ["." * 50 for _ in range(50)]
empty_maze[0] = "S" + empty_maze[0][1:]
empty_maze[-1] = empty_maze[-1][:-1] + "E"
mazes["Empty (50x50)"] = builder.build_from_string_list(empty_maze)
#Средний лабиринт 50x50 с тупиками
medium_maze = []
for y in range(50):
if y == 0:
row = "S" + "." * 49
elif y == 49:
row = "." * 49 + "E"
elif y % 2 == 1:
row = "#" * 45 + "." * 5 if y % 4 == 1 else "." * 5 + "#" * 45
else:
row = "." * 50
medium_maze.append(row)
mazes["Medium with dead ends (50x50)"] = builder.build_from_string_list(medium_maze)
# Большой лабиринт 100x100
large_maze = []
for y in range(100):
if y == 0:
row = "S" + "." * 99
elif y == 99:
row = "." * 99 + "E"
elif y % 2 == 1:
row = ("#" * 9 + ".") * 10
else:
row = "." * 100
large_maze.append(row)
mazes["Large (100x100)"] = builder.build_from_string_list(large_maze)
# Лабиринт без выхода
no_exit_maze = [
"S....#....",
"##########",
"##########",
"##########",
"##########",
"##########",
"##########",
"##########",
"##########",
"######...E"
]
mazes["No exit (10x10)"] = builder.build_from_string_list(no_exit_maze)
return mazes
def run_experiments() -> None:
mazes = create_test_mazes()
strategies = {
"BFS": BFSStrategy(),
"DFS": DFSStrategy(),
"A*": AStarStrategy(),
"Dijkstra": DijkstraStrategy()
}
results = []
print("=" * 80)
print("ЗАПУСК ЭКСПЕРИМЕНТОВ ПО СРАВНЕНИЮ АЛГОРИТМОВ ПОИСКА ПУТИ")
print("=" * 80)
for maze_name, maze in mazes.items():
print(f"\nТестирование: {maze_name}")
print("-" * 60)
for strategy_name, strategy in strategies.items():
solver = MazeSolver(maze, strategy)
runs = 5
total_time = 0
path = []
stats = None
for _ in range(runs):
path, stats = solver.solve()
total_time += stats.time_ms
avg_time = total_time / runs
results.append([
maze_name,
strategy_name,
f"{avg_time:.4f}",
stats.visited_cells,
stats.path_length
])
print(f" {strategy_name:10} -> "
f"Время: {avg_time:8.3f}мс | "
f"Посещено: {stats.visited_cells:5} | "
f"Длина пути: {stats.path_length:3}")
with open("results_all.csv", "w", newline="", encoding="utf-8") as csvfile:
writer = csv.writer(csvfile)
writer.writerow(["Лабиринт", "Стратегия", "Время (мс)",
"Посещено клеток", "Длина пути"])
writer.writerows(results)
print("\n" + "=" * 80)
print("Все эксперименты завершены!")
print("Результаты сохранены в файл 'results_all.csv'")
print("=" * 80)
def demonstrate_visualization() -> None:
"""Демонстрация визуализации и паттерна Observer."""
builder = TextMazeBuilder()
maze_data = [
"S...#.....",
".###.####.",
".....#....",
"####.#####",
".....#....",
".#######..",
"..........",
"######.###",
"..........",
".........E"
]
maze = builder.build_from_string_list(maze_data)
strategy = AStarStrategy()
solver = MazeSolver(maze, strategy)
console_view = ConsoleView()
solver.add_observer(console_view)
print("\nДЕМОНСТРАЦИЯ ВИЗУАЛИЗАЦИИ")
print("=" * 40)
path, stats = solver.solve()
print("\nНайденный путь:")
console_view.render(maze, path)
print(f"\nСтатистика: {stats}")
print(f" Время: {stats.time_ms:.3f}мс")
print(f" Посещено клеток: {stats.visited_cells}")
print(f" Длина пути: {stats.path_length}")
if __name__ == "__main__":
demonstrate_visualization()
run_experiments()

View File

@ -0,0 +1,21 @@
Лабиринт,Стратегия,Время (мс),Посещено клеток,Длина пути
Small (10x10),BFS,0.1173,59,27
Small (10x10),DFS,0.0961,49,27
Small (10x10),A*,0.1480,50,27
Small (10x10),Dijkstra,0.1623,60,27
Empty (50x50),BFS,5.1892,2500,99
Empty (50x50),DFS,3.1591,1275,1275
Empty (50x50),A*,13.0123,2500,99
Empty (50x50),Dijkstra,10.5962,2500,99
Medium with dead ends (50x50),BFS,3.3357,1420,1083
Medium with dead ends (50x50),DFS,2.9541,1275,1275
Medium with dead ends (50x50),A*,4.8367,1404,1083
Medium with dead ends (50x50),Dijkstra,3.9227,1420,1083
Large (100x100),BFS,10.6456,5590,199
Large (100x100),DFS,10.8020,4933,4519
Large (100x100),A*,28.2500,5140,199
Large (100x100),Dijkstra,24.3427,5590,199
No exit (10x10),BFS,0.0105,5,0
No exit (10x10),DFS,0.0090,5,0
No exit (10x10),A*,0.0116,5,0
No exit (10x10),Dijkstra,0.0100,5,0
1 Лабиринт Стратегия Время (мс) Посещено клеток Длина пути
2 Small (10x10) BFS 0.1173 59 27
3 Small (10x10) DFS 0.0961 49 27
4 Small (10x10) A* 0.1480 50 27
5 Small (10x10) Dijkstra 0.1623 60 27
6 Empty (50x50) BFS 5.1892 2500 99
7 Empty (50x50) DFS 3.1591 1275 1275
8 Empty (50x50) A* 13.0123 2500 99
9 Empty (50x50) Dijkstra 10.5962 2500 99
10 Medium with dead ends (50x50) BFS 3.3357 1420 1083
11 Medium with dead ends (50x50) DFS 2.9541 1275 1275
12 Medium with dead ends (50x50) A* 4.8367 1404 1083
13 Medium with dead ends (50x50) Dijkstra 3.9227 1420 1083
14 Large (100x100) BFS 10.6456 5590 199
15 Large (100x100) DFS 10.8020 4933 4519
16 Large (100x100) A* 28.2500 5140 199
17 Large (100x100) Dijkstra 24.3427 5590 199
18 No exit (10x10) BFS 0.0105 5 0
19 No exit (10x10) DFS 0.0090 5 0
20 No exit (10x10) A* 0.0116 5 0
21 No exit (10x10) Dijkstra 0.0100 5 0