我有一本字典词典。键是图中的节点。例如,让我们假设图中的节点i由字典中的键i表示。与该键对应的值也是字典,其中键是图中节点i的邻居。这些键具有默认值1.让我们考虑以下示例 -
图中的节点是 - [1,2,3,4,5,6]
邻居:
1->[2,4,5,6]
2->[3]
3->[4,6]
4->[1,6]
5->[1]
6->[1,3,4]
所以字典字典看起来像这样:
{1:{2:1,4:1,5:1,6:1},2:{3:1},3:{4:1,6:1},4:{1:1,6:1},5:{1:1},6:{1:1,3:1,4:1}}
现在,在我尝试实现的算法的不同阶段,我需要从其他节点的邻居列表中删除所有出现的节点x。如果x = 4,则删除后,字典字典应如下所示:
{1:{2:1,5:1,6:1},2:{3:1},3:{6:1},4:{1:1,6:1},5:{1:5},6:{1:1,3:1}}
我使用字典而不是列表字典来使删除有效。但它仍然很昂贵。
这样做效率最高的是什么?
答案 0 :(得分:3)
使用词典理解:
{ok: {ik: iv for ik, iv in ov.iteritems() if ik != x}
for ok, ov in yourdict.iteritems()}
这会重建您的词典,而省略内部词典中与x
匹配的所有键。
在Python 3中替换iteritems()
items()
。
演示:
>>> yourdict = {1:{2:1,4:1,5:1,6:1},2:{3:1},3:{4:1,6:1},4:{1:1,6:1},5:{1:5},6:{1:1,3:1,4:1}}
>>> x = 4
>>> {ok: {ik: iv for ik, iv in ov.iteritems() if ik != x}
... for ok, ov in yourdict.iteritems()}
{1: {2: 1, 5: 1, 6: 1}, 2: {3: 1}, 3: {6: 1}, 4: {1: 1, 6: 1}, 5: {1: 5}, 6: {1: 1, 3: 1}}
答案 1 :(得分:2)
您选择的结构可能不是最有效的结构。套装可能只适合账单。
我不太明白你的连接是箭头式的单向连接还是双向连接。我假设单向连接,因为2是1的邻居,但反之亦然。如果是这种情况,我们需要跟踪“从”和“到”。
我已修改您的代码以使用集合而不是字典来提高效率。
pointing_to = {
1: set([2,4,5,6]),
2: set([3]),
3: set([4,6]),
4: set([1,6]),
5: set([1]),
6: set([1,3,4]) }
pointed_by = {
1: set([4,5,6]),
2: set([1]),
3: set([2,6]),
4: set([1,3,6]),
5: set([1]),
6: set([1,3,4]) }
(当然,pointed_by
可以用一小段代码创建,我只是写出来展示这个想法。)
现在,如果您需要删除与节点tbr
之间的所有连接:
# remove tbr from pointing_to lists of all neighbours pointing to tbr
# (connections from other nodes to tbr
for n in pointed_by[tbr]:
pointing_to[n].remove(tbr)
# after this tar is pointed by no neighbour
pointed_by[tbr] = set()
# repeat for opposite direction (connections from tbr to other nodes)
for n in pointing_to[tbr]:
pointed_by[n].remove(tbr)
pointing_to[tbr] = set()
这应该相对快速且易于理解。
如果只有双向连接,一个字典和上面代码的一半就足够了。
关于表现的几句话。
可以看出,这种方法的循环非常短。它仅通过要删除的节点一端的连接进行迭代。在该级别,连接总数无关紧要,也不是总点数。
然而,更深层次的集合和字典查找时间并不独立于这些字典和集合的大小。我的猜测是O(log n),其中n是点或连接的总数,但有人可能更了解实际的实现。
使用套装比使用字典要快一些,但差别很小,因为它们几乎与引擎盖下面的东西相同。简单的集合操作往往非常快。
我的猜测是,对于非常小的数据集,线性搜索方法更快,因为它们可能使用列表推导和c。使用更大的数据,这将更有效。
答案 2 :(得分:0)
这将在原地进行。您可以先使用copy.deepcopy
将其作为副本。
t = {1:{2:1,4:1,5:1,6:1},
2:{3:1},
3:{4:1,6:1},
4:{1:1,6:1},
5:{1:5},
6:{1:1,3:1,4:1}}
for k,v in t.iteritems():
v.pop(4, None)
print t
{1: {2: 1, 5: 1, 6: 1},
2: {3: 1},
3: {6: 1},
4: {1: 1, 6: 1},
5: {1: 5},
6: {1: 1, 3: 1}}
您可以将其封装为辅助函数:
def remove_node(graph, node, inplace=True):
import copy
temp_graph = copy.deepcopy(graph) if not inplace else graph
for k,v in temp_graph.iteritems():
v.pop(node, None)
return temp_graph