一般来说python建图使用列表嵌套列表或者列表嵌套字典,这种建图方式比较好理解但是有的时候表示起来不是特别方便,其中一种比较方便的建图方式使用四个数组来存储图中节点和边的信息:e,ne,h,w,其中e[idx]表示当前第idx边的终点对应的节点编号(idx从0开始编号),ne[idx]表示第idx条边的下一条边,h[idx]为表头,表示当前节点编号为idx出发的边属于第几条边,w[idx]当前第idx条边的权重,对于无向图来说则需要创建两个方向,其中0-1为一组反向边,2-3为一组反向边....,其实举个例子就很好理解了,下面是有向图的例子:
比如遍历节点编号为3的邻接点,首先找到节点3的表头h[3],h[3]表示当前节点编号为3的节点总共有多少条出发的边,在遍历的时候是按照创建边的逆序遍历其邻接点的,例如遍历编号为3的节点的时候,第一个遍历的是编号为4的节点,然后是2这个节点,最后是1这个节点,所以是根据边创建的顺序逆序遍历的,这种建图方式的一个好处是对于无向图很快能够标记其反向边,因为创建边的时候是按照第几条边来表示对应的邻接点的,对于反向边来说0-1为一组,2-3为一组,4-5为一组,...并且这种创建方式需要预先估算节点和边的数量,h[n + 10],ne[m + 10],w[m + 10],e[m + 10],其中n为节点的数量,m为边的数量,一般需要开大一点避免数组越界的问题,如果图中没有边的权重那么w数组可以省略,我们可以在理解的基础上进行记忆这样建图的时候可以直接默写模板。
class Solution:
h, e, w, ne, idx = None, None, None, None, None
def add(self, a: int, b: int, w: int):
self.e[self.idx] = b
self.ne[self.idx] = self.h[a]
self.w[self.idx] = w
self.h[a] = self.idx
self.idx += 1
def process(self):
n = 50
self.h, self.e, self.w, self.ne = [-1] * n, [0] * n * 2, [0] * n * 2, [0] * n * 2
self.idx = 0
# 3-->1, 3-->2, 3-->4
self.add(3, 1, 10)
self.add(3, 2, 20)
self.add(3, 4, 30)
# 遍历邻接表
i = self.h[3]
while i != -1:
j = self.e[i]
# 输出当前节点3的邻接节点编号
print(j)
i = self.ne[i]
if __name__ == "__main__":
Solution().process()