我认为在填充邻居列表或过滤邻居时使用控制流语句来检查条件都是很好的方法——我的自然倾向是生成所有可能的邻居并过滤它们,这可能不是真正巨大的最佳想法图表。
这可以作为一个函数来完成,但是以防万一您需要其他类型的图形或需要其他功能(例如返回两个点是否连接的某些方法),您不妨开始一个类,这里只是一个你如何做到这一点的例子:
import typing
import itertools
class Graph(object):
def __init__(self,
shape: typing.Tuple[int, int],
connectivity: str = "grid"):
self.nodes = {} # type: typing.Dict[tuple, list]
self.shape = shape
self.connectivity = connectivity
self._init_nodes()
def _init_nodes(self):
# iterate through all combinations of coordinates
for x, y in itertools.product(range(self.shape[0]), range(self.shape[1])):
# switch in case there are other connectivity types, but for this example just grid
if self.connectivity == "grid":
# make and all possible neighbors
neighbors = [(x-1, y), (x+1, y), (x, y-1), (x, y+1)]
# filter impossible neighbors
neighbors = [n for n in neighbors if 0 <= n[0] <= self.shape[0]-1 and 0 <= n[1] <= self.shape[1]-1]
self.nodes[(x,y)] = neighbors
else:
raise NotImplementedError('only grid for now!!!')
它提供了一个连接节点的字典,就像你在你的 OP 中一样,虽然我不太确定这是否回答了问题 b/c 无法说出你在最后一段中要求的内容(我的错) ,如果没有,请告诉我:
>>> a_graph = Graph((5,5))
>>> pprint(a_graph.nodes)
{(0, 0): [(1, 0), (0, 1)],
(0, 1): [(1, 1), (0, 0), (0, 2)],
(0, 2): [(1, 2), (0, 1), (0, 3)],
(0, 3): [(1, 3), (0, 2), (0, 4)],
(0, 4): [(1, 4), (0, 3)],
(1, 0): [(0, 0), (2, 0), (1, 1)],
(1, 1): [(0, 1), (2, 1), (1, 0), (1, 2)],
(1, 2): [(0, 2), (2, 2), (1, 1), (1, 3)],
(1, 3): [(0, 3), (2, 3), (1, 2), (1, 4)],
(1, 4): [(0, 4), (2, 4), (1, 3)],
(2, 0): [(1, 0), (3, 0), (2, 1)],
(2, 1): [(1, 1), (3, 1), (2, 0), (2, 2)],
(2, 2): [(1, 2), (3, 2), (2, 1), (2, 3)],
(2, 3): [(1, 3), (3, 3), (2, 2), (2, 4)],
(2, 4): [(1, 4), (3, 4), (2, 3)],
(3, 0): [(2, 0), (4, 0), (3, 1)],
(3, 1): [(2, 1), (4, 1), (3, 0), (3, 2)],
(3, 2): [(2, 2), (4, 2), (3, 1), (3, 3)],
(3, 3): [(2, 3), (4, 3), (3, 2), (3, 4)],
(3, 4): [(2, 4), (4, 4), (3, 3)],
(4, 0): [(3, 0), (4, 1)],
(4, 1): [(3, 1), (4, 0), (4, 2)],
(4, 2): [(3, 2), (4, 1), (4, 3)],
(4, 3): [(3, 3), (4, 2), (4, 4)],
(4, 4): [(3, 4), (4, 3)]}