我建议您退后一步,以不同的方式思考您的问题。根据您的问题,您正在尝试识别 lsta 对列表中的连接子图。根据您的说法,这些图是简单连接的 - 也就是说,(a,b) 与 (b,a) 相同,没有方向性。
查看前两对,您有0,1 和0,2。这会产生一个由{0,1,2} 组成的子图,因为您并不真正关心哪一端是常见的。 set 类型将是您解决方案的关键。与其担心递归,不如尝试管理集合以获得您想要的结果。
首先,导入集合,然后创建您的默认字典。您不需要直接导入 defaultdict,因为您只需要输入一次,这会稍微清理一下:
import collections
Subgraphs = collections.defaultdict(set)
现在让我们添加您的初始测试数据。 请注意:这里有一个“错误”,因为最后一对 (8,17) 将子图连成一个。你可能不希望这样。
lsta = [
[ 0, 1], [ 0, 2], [ 1, 3], [ 2, 4],
[ 3, 5], [ 4, 6], [ 5, 7], [ 7, 9],
[ 8, 10], [ 8, 11], [10, 12], [11, 13],
[11, 14], [12, 15], [12, 16], [ 6, 17],
[ 8, 17],
]
现在让我们初始化集合。每个 node(整数)将指向它所连接的集合。最初,节点只连接到自己,因此每个键 K 将指向一个集合 {K}。
for a,b in lsta:
Subgraphs[a].add(a)
Subgraphs[b].add(b)
现在让我们合并集合。每对(a,b) 表示a 和b 已连接。这意味着这两个节点应该共享 same 节点集,因为它们(通过彼此)连接到所有邻居的联合。
我们假设节点 A 指向一个集合,并且该集合中的所有节点也指向同一个集合。 (这有点儿 Python 技巧。它们不是同一集合的 副本,而是对内存中相同对象的实际 引用。)这意味着更新集合可以一次性完成,影响所有成员。
for a,b in lsta:
seta = Subgraphs[a]
setb = Subgraphs[b]
others = setb - seta
seta |= setb
print("Processing (%d, %d): %s" % (a, b, seta))
print("... updating: ", others)
for o in others:
Subgraphs[o] = seta
此时,Subgraphs 字典中的所有键(节点)都应指向包含其所有可达邻居的集合。我们将打印输入和结果数据,然后交给您。
print("\n***********")
print(lsta)
print(Subgraphs)
您可能想要删除最后一对:[8,17]。此外,您可能想要识别唯一的子图。我不知道你在用这段代码做什么,但如果你真的需要子图,你可以把它们变成 frozenset 对象,然后可以将其添加到 set 以产生不同的集合。或者,您可以只迭代 Subgraphs dict 的键,将集合合并到 seen 集合中并跳过 seen 中已有的任何键。
这是我使用 lsta 数据原样运行它时得到的输出:
Processing (0, 1): {0, 1}
... updating: {1}
Processing (0, 2): {0, 1, 2}
... updating: {2}
Processing (1, 3): {0, 1, 2, 3}
... updating: {3}
Processing (2, 4): {0, 1, 2, 3, 4}
... updating: {4}
Processing (3, 5): {0, 1, 2, 3, 4, 5}
... updating: {5}
Processing (4, 6): {0, 1, 2, 3, 4, 5, 6}
... updating: {6}
Processing (5, 7): {0, 1, 2, 3, 4, 5, 6, 7}
... updating: {7}
Processing (7, 9): {0, 1, 2, 3, 4, 5, 6, 7, 9}
... updating: {9}
Processing (8, 10): {8, 10}
... updating: {10}
Processing (8, 11): {8, 10, 11}
... updating: {11}
Processing (10, 12): {8, 10, 11, 12}
... updating: {12}
Processing (11, 13): {8, 10, 11, 12, 13}
... updating: {13}
Processing (11, 14): {8, 10, 11, 12, 13, 14}
... updating: {14}
Processing (12, 15): {8, 10, 11, 12, 13, 14, 15}
... updating: {15}
Processing (12, 16): {16, 8, 10, 11, 12, 13, 14, 15}
... updating: {16}
Processing (6, 17): {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}
... updating: {17}
Processing (8, 17): {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}
... updating: {0, 1, 2, 3, 4, 5, 6, 7, 9, 17}
*********
LSTA: [[0, 1], [0, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 7], [7, 9], [8, 10], [8, 11], [10, 12], [11, 13], [11, 14], [12, 15], [12, 16], [6, 17], [8, 17]]
Subgraphs: defaultdict(<class 'set'>, {0: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 1: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 2: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 3: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 4: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 5: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 6: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 7: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 8: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 9: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 10: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 11: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 12: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 13: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 14: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 15: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 16: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 17: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}})
这是我从 lsta 中删除 [8,17] 对时的结果:
Processing (0, 1): {0, 1}
... updating: {1}
Processing (0, 2): {0, 1, 2}
... updating: {2}
Processing (1, 3): {0, 1, 2, 3}
... updating: {3}
Processing (2, 4): {0, 1, 2, 3, 4}
... updating: {4}
Processing (3, 5): {0, 1, 2, 3, 4, 5}
... updating: {5}
Processing (4, 6): {0, 1, 2, 3, 4, 5, 6}
... updating: {6}
Processing (5, 7): {0, 1, 2, 3, 4, 5, 6, 7}
... updating: {7}
Processing (7, 9): {0, 1, 2, 3, 4, 5, 6, 7, 9}
... updating: {9}
Processing (8, 10): {8, 10}
... updating: {10}
Processing (8, 11): {8, 10, 11}
... updating: {11}
Processing (10, 12): {8, 10, 11, 12}
... updating: {12}
Processing (11, 13): {8, 10, 11, 12, 13}
... updating: {13}
Processing (11, 14): {8, 10, 11, 12, 13, 14}
... updating: {14}
Processing (12, 15): {8, 10, 11, 12, 13, 14, 15}
... updating: {15}
Processing (12, 16): {16, 8, 10, 11, 12, 13, 14, 15}
... updating: {16}
Processing (6, 17): {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}
... updating: {17}
*********
LSTA: [[0, 1], [0, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 7], [7, 9], [8, 10], [8, 11], [10, 12], [11, 13], [11, 14], [12, 15], [12, 16], [6, 17]]
Subgraphs: defaultdict(<class 'set'>, {0: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 1: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 2: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 3: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 4: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 5: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 6: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 7: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 8: {16, 8, 10, 11, 12, 13, 14, 15}, 9: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 10: {16, 8, 10, 11, 12, 13, 14, 15}, 11: {16, 8, 10, 11, 12, 13, 14, 15}, 12: {16, 8, 10, 11, 12, 13, 14, 15}, 13: {16, 8, 10, 11, 12, 13, 14, 15}, 14: {16, 8, 10, 11, 12, 13, 14, 15}, 15: {16, 8, 10, 11, 12, 13, 14, 15}, 16: {16, 8, 10, 11, 12, 13, 14, 15}, 17: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}})