【发布时间】:2017-08-19 20:31:25
【问题描述】:
我有一个字典,它的键是整数,但是当迭代它时,我希望整数以未排序的顺序出现。在一个简单的例子中,这似乎适用于OrderedDict:
In [16]: d3 = OrderedDict({k: k+1 for k in [3, 2, 1]})
In [17]: for k, v in d3.items():
...: print(k, v)
...:
3 4
2 3
1 2
但是,在我的“真实”应用程序中,这并没有按预期工作。我正在尝试识别有向图的强连通分量 (SCC)。在我的Graph 类中,我正在编写strongly_connected_component 方法:
import pytest
import collections
class Node(object):
def __init__(self):
self.color = 'white'
self.parent = None
self.d = None # Discovery time
self.f = None # Finishing time
class Graph(object):
def __init__(self, edges):
self.edges = edges
self.nodes = self.initialize_nodes()
self.adj = self.initialize_adjacency_list()
def initialize_nodes(self, node_indices=None):
if node_indices is None:
node_indices = sorted(list(set(node for edge in self.edges for node in edge)))
return collections.OrderedDict({node_index: Node() for node_index in node_indices})
def initialize_adjacency_list(self):
A = {node: [] for node in self.nodes}
for edge in self.edges:
u, v = edge
A[u].append(v)
return A
def dfs(self):
self.time = 0
for u, node in self.nodes.items():
if node.color == 'white':
self.dfs_visit(u)
def dfs_visit(self, u):
self.time += 1
self.nodes[u].d = self.time
self.nodes[u].color = 'gray'
for v in self.adj[u]:
if self.nodes[v].color == 'white':
self.nodes[v].parent = u
self.dfs_visit(v)
self.nodes[u].color = 'black'
self.time += 1
self.nodes[u].f = self.time
@staticmethod
def transpose(edges):
return [(v,u) for (u,v) in edges]
def strongly_connected_components(self):
self.dfs()
finishing_times = {u: node.f for u, node in self.nodes.items()}
# print(finishing_times)
self.__init__(self.transpose(self.edges))
node_indices = sorted(finishing_times, key=self.nodes.get, reverse=True)
# print(node_indices)
self.nodes = self.initialize_nodes(node_indices)
# print(self.nodes)
为了验证dfs 方法是否有效,我复制了以下来自 Cormen 等人的示例,算法简介:
我将节点标签 u 到 z 分别替换为数字 1 到 6。下面的测试,
def test_dfs():
'''This example is taken from Cormen et al., Introduction to Algorithms (3rd ed.), Figure 22.4'''
edges = [(1,2), (1,4), (4,2), (5,4), (2,5), (3,5), (3,6), (6,6)]
graph = Graph(edges)
graph.dfs()
print("\n")
for index, node in graph.nodes.items():
print index, node.__dict__
打印
1 {'color': 'black', 'd': 1, 'parent': None, 'f': 8}
2 {'color': 'black', 'd': 2, 'parent': 1, 'f': 7}
3 {'color': 'black', 'd': 9, 'parent': None, 'f': 12}
4 {'color': 'black', 'd': 4, 'parent': 5, 'f': 5}
5 {'color': 'black', 'd': 3, 'parent': 2, 'f': 6}
6 {'color': 'black', 'd': 10, 'parent': 3, 'f': 11}
很容易看出它与书中的图 22.4(p) 相对应。为了计算 SCC,我必须实现以下伪代码:
在我的strongly_connected_components 方法中,我通过完成时间以相反的顺序订购node_indices。由于它在initialize_nodes 方法中被初始化为OrderedDict,因此我希望通过以下测试:
def test_strongly_connected_components():
edges = [(1,2), (1,4), (4,2), (5,4), (2,5), (3,5), (3,6), (6,6)]
graph = Graph(edges)
graph.strongly_connected_components()
assert graph.nodes.keys() == [3, 2, 1, 4, 6, 5]
if __name__ == "__main__":
pytest.main([__file__, "-s"])
因为[3, 2, 1, 4, 6, 5] 是深度优先搜索中节点“完成”的相反顺序。但是,此测试失败:
=================================== FAILURES ===================================
______________________ test_strongly_connected_components ______________________
def test_strongly_connected_components():
edges = [(1,2), (1,4), (4,2), (5,4), (2,5), (3,5), (3,6), (6,6)]
graph = Graph(edges)
graph.strongly_connected_components()
> assert graph.nodes.keys() == [3, 2, 1, 4, 6, 5]
E assert [1, 2, 3, 4, 5, 6] == [3, 2, 1, 4, 6, 5]
E At index 0 diff: 1 != 3
E Use -v to get the full diff
scc.py:94: AssertionError
为什么键没有按照OrderedDict初始化时指定的顺序保留?
【问题讨论】:
-
在第一个例子中,你很“幸运” dict 保留了顺序......这给你的印象是这样做是正确的。但是不。