Compare commits

..

No commits in common. "511653fafc46de951a2d6a77e5623c790fe18960" and "714ea579ddad174bc83042ea0eef3ec84c5246a4" have entirely different histories.

8 changed files with 132 additions and 2278946 deletions

View File

@ -1,109 +1,109 @@
Structure,Mode,Operation,Time (sec)
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
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
HashTable,sorted,find (trial 1),0.000087
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 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 4),0.000049
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
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

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

Binary file not shown.

View File

@ -11,6 +11,7 @@ threading.stack_size(64*1024*1024)
def ll_insert(head, name, phone):
"""Добавляет запись или обновляет телефон, если имя уже существует. Возвращает новую голову списка."""
current = head
while current is not None:
if current["name"] == name:
@ -22,6 +23,7 @@ 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:
@ -30,6 +32,7 @@ def ll_find(head, name):
return None
def ll_delete(head, name):
"""Удаляет узел по имени. Возвращает новую голову списка."""
current = head
previous = None
@ -46,6 +49,7 @@ def ll_delete(head, name):
return head
def ll_list_all(head):
"""Собирает все записи в список и сортирует их по имени."""
entries = []
current = head
while current is not None:
@ -56,21 +60,26 @@ 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
@ -82,6 +91,7 @@ def ht_list_all(buckets):
def bst_insert(root, name, phone):
"""Рекурсивно вставляет узел или обновляет телефон."""
if root is None:
return {"name": name, "phone": phone, "left": None, "right": None}
@ -95,6 +105,7 @@ def bst_insert(root, name, phone):
return root
def bst_find(root, name):
"""Рекурсивный поиск по дереву."""
if root is None:
return None
@ -106,6 +117,7 @@ def bst_find(root, name):
return bst_find(root["right"], name)
def bst_delete(root, name):
"""Рекурсивное удаление узла из BST."""
if root is None:
return None
@ -130,6 +142,7 @@ def bst_delete(root, name):
return root
def bst_list_all(root):
"""Центрированный обход дерева для сбора записей."""
entries = []
def _inorder(node):
if node is not None:
@ -166,7 +179,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)
@ -178,7 +191,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)
@ -190,7 +203,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)
@ -221,17 +234,23 @@ 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
@ -288,5 +307,6 @@ if __name__ == '__main__':
benchmark_thread.start()
benchmark_thread.join()
# Дополнительно: если графики не показались автоматически
# Можно вызвать функцию напрямую после завершения потока
print("\nПрограмма завершена. Проверьте файл 'performance_charts.png'")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,484 +0,0 @@
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

@ -1,21 +0,0 @@
Лабиринт,Стратегия,Время (мс),Посещено клеток,Длина пути
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