【问题标题】:Convert a list of weighted edges into an adjacency matrix in a memory-efficient way以节省内存的方式将加权边列表转换为邻接矩阵
【发布时间】:2021-10-24 17:43:41
【问题描述】:

使用 Python,如何以节省内存的方式将加权边列表转换为对称邻接矩阵?

例如,考虑以下包含 4 个节点和 3 条边的加权边列表:

A B 1
A C 2
C D 3

那么输出邻接矩阵如下:

0 1 2 0
1 0 0 0
2 0 0 3
0 0 3 0

我希望以一种节省内存的方式来执行此操作 - 100000 x 100000 邻接矩阵(10**10 个值)。注意矩阵是对称的,所有的对角线值都是0。

【问题讨论】:

  • 所以你想要一个密集矩阵?为什么不直接转换成稀疏的呢?
  • @DaniMesejo 我打算使用一种算法将图形转换为完整图形。
  • 你的意思是一个包含所有可能边的图?
  • @DaniMesejo 是的。

标签: python adjacency-matrix


【解决方案1】:

您可以使用稀疏矩阵。为了使其更易于访问,请使用稀疏矩阵字典。使用相邻顶点的元组作为字典的键。

nodes = ['A','B','C','D']
graph = {('A','B'):1, ('A','C'): 2, ('C','D'): 3}

为了访问节点,我们使用了两个嵌套的 for 循环。对于每对节点,我们可以检查是否存在 O(1) 时间复杂度的边。 例如:

for i in nodes:
    for j in nodes:
        if (i,j) in graph:
            print(i,j,graph[(i,j)])
        else:
            print("Edge not present.")

即使你用字符来表示节点,你也可以在 该方法与正则矩阵法具有相同的时间复杂度。但空间复杂度大大降低。从图字典中添加新边或删除边非常容易。

【讨论】:

    【解决方案2】:

    您可以使用字典字典,并且只将边缘及其权重存储一次。使用函数访问权重将允许您根据需要反转参数顺序以获取和设置权重值。

    def getWeight(adj,a,b):
        return getWeight(adj,b,a) if a>b else adj.get(a,{}).get(b,0)
    
    def setWeight(adj,a,b,w):
        if a>b: setWeight(adj,b,a,w)
        else:   adj.setdefault(a,{})[b] = w
        
    edges  = [('A','B',1),('A','C',2),('C','D',3)]
    adj    = {v:{} for e in edges for v in e[:2]}
    
    for a,b,w in edges:
        setWeight(adj,a,b,w)
    

    输出:

    print(adj)
    {'A': {'B': 1, 'C': 2}, 'B': {}, 'C': {'D': 3}, 'D': {}}
    
    print(getWeight(adj,'B','A')) # 1
    print(getWeight(adj,'A','B')) # 1
    print(getWeight(adj,'D','A')) # 0
    

    如果您在另一个列表中的某处有顶点,则只需将边权重存储在字典中,这将使其内存效率稍高:

    def getWeight(adj,a,b):
        return adj[a,b] if (a,b) in adj else adj.get((b,a),0)
    
    def setWeight(adj,a,b,w):
        if (b,a) in adj: adj[b,a] = w
        else:            adj[a,b] = w
        
    edges  = [('A','B',1),('A','C',2),('C','D',3)]
    adj    = {(a,b):w for a,b,w in edges}
    
    print(adj)
    {('A', 'B'): 1, ('A', 'C'): 2, ('C', 'D'): 3}
    
    print(getWeight(adj,'B','A')) # 1
    print(getWeight(adj,'A','B')) # 1
    print(getWeight(adj,'D','A')) # 0
    

    【讨论】:

      猜你喜欢
      • 2014-09-04
      • 1970-01-01
      • 1970-01-01
      • 2020-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多