Я бы использовал наборы, как было сказано, но я также использовал бы кучу, чтобы найти минимальный элемент (тот, который будет следующим current
). Это потребует сохранения как openSet, так и openHeap, но память не должна быть проблемой. Также устанавливает insert в O (1) и кучу в O (log N), поэтому они будут быстрыми. Единственная проблема заключается в том, что модуль heapq не предназначен для использования с ним ключей. Лично я бы просто изменил его, чтобы использовать ключи. Это не должно быть очень сложно. Кроме того, вы можете просто использовать кортежи (tile.H, tile) в куче.
Кроме того, я бы следовал идее aaronasterling об использовании итерации вместо рекурсии, но также добавлял элементы в конец path
и наоборот path
в конце. Причина в том, что вставка элемента на 0-м месте в списке очень медленная (O (N), я полагаю), а добавление - O (1), если я правильно помню. Окончательный код для этой части будет:
def retracePath(c):
path = [c]
while c.parent is not None:
c = c.parent
path.append(c)
path.reverse()
return path
Я поставил путь возврата в конце, потому что оказалось, что он должен из вашего кода.
Вот окончательный код, использующий наборы, кучи, а что нет:
import heapq
def aStar(graph, current, end):
openSet = set()
openHeap = []
closedSet = set()
def retracePath(c):
path = [c]
while c.parent is not None:
c = c.parent
path.append(c)
path.reverse()
return path
openSet.add(current)
openHeap.append((0, current))
while openSet:
current = heapq.heappop(openHeap)[1]
if current == end:
return retracePath(current)
openSet.remove(current)
closedSet.add(current)
for tile in graph[current]:
if tile not in closedSet:
tile.H = (abs(end.x - tile.x)+abs(end.y-tile.y))*10
if tile not in openSet:
openSet.add(tile)
heapq.heappush(openHeap, (tile.H, tile))
tile.parent = current
return []