【问题标题】:Graph updating algorithm图更新算法
【发布时间】:2012-07-20 19:15:29
【问题描述】:

我有一个使用邻接表表示的(无向)图,例如

a: b, c, e
b: a, d
c: a, d
d: b, c
e: a

图中的每个节点都链接到其他节点的列表

我想在给定某些节点的一些新列表的情况下更新这样的图表,例如

a: b, c, d

其中a 不再连接到e,而是连接到一个新节点d

对图形执行此类更新的高效(时间和空间方面)算法是什么?

【问题讨论】:

  • 如果您计划大量添加和删除边,那么您可能希望使用邻接集而不是列表。

标签: python algorithm graph-theory graph-algorithm


【解决方案1】:

使用邻接网格将使其 O(n) 更新,但会占用 n^2 空间,无论图有多稀疏。 (通过反转行和列来更新每个更改的关系来轻松完成。)

使用列表可以将更新时间增加到 O(n^2),但对于稀疏图不会花费大量时间,并且会节省大量空间。

【讨论】:

  • 我不擅长数据结构,但邻接表不应该只占用 O(2n) 空间吗?每条边总体上只出现两次。
  • 可能的边数为 n^2,其中有 n 个节点。
  • 或者使用具有 O(n+2*nnz) 存储空间的实际稀疏矩阵类,其中 nnz=边数。大量可用的 Python 实现,包括 scipy。
  • @bdares,感谢您的建议。您提出的邻接网格与邻接矩阵不一样吗?
【解决方案2】:

典型的更新是del edge a,e; add edge a,d,但您的更新看起来像是顶点a 的新邻接列表。所以只需找到a 邻接列表并替换它。这应该是 O(log n) 时间(假设邻接列表的排序数组,如您的描述中所示)。

【讨论】:

  • 我不知道这是否足够:OP 是否也必须更新 de 的邻接列表?
  • @DSM,确切地说,即使提供的列表可能仅适用于可用节点的子集,但更改可能会影响到此节点子集之外。
【解决方案3】:

也许我遗漏了一些东西,但是使用节点标签(字符串或数字)的字典(或默认字典)来设置不是最快的吗?在这种情况下,更新可能如下所示:

def update(graph, node, edges, undirected=True):
    # graph: dict(str->set(str)), node: str, edges: set(str), undirected: bool
    if undirected:
        for e in graph[node]:
            graph[e].remove(node)
        for e in edges:
            graph[e].add(node)
    graph[node] = edges

使用集合和字典,在其他节点的边集中添加和删除节点应该是 O(1),与更新节点本身的边集相同,所以这应该只是 O( 2n) 对于两个循环,n 是节点的平均边数。

【讨论】:

  • 我认为这个答案是最好的。我最初认为通过旧集和新集之间的差异(在两个方向上)来找到删除和添加的边的子集是有益的,但是在给它一点点之后,虽然我认为这实际上不会改善完全没有性能(甚至可能更糟,尽管仍然是 O(n))。
猜你喜欢
  • 1970-01-01
  • 2019-07-14
  • 2013-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多