我一直在尝试对Python中的BFS实现进行性能优化,而我最初的实现是使用双端队列来存储要扩展的节点队列和一个字典来存储相同的节点,这样我就可以高效地查找它是否已经打开。
我试图通过移至OrderedDict来优化(简单性和效率)。但是,这会花费更多时间。完成400个样本搜索时,双引号/字典需要2秒,而仅OrderedDict则需要3.5秒。
我的问题是,如果OrderedDict的功能与两个原始数据结构相同,那么它的性能至少不应该相似吗?还是我在这里想念什么?下面的代码示例。
仅使用OrderedDict:
open_nodes = OrderedDict() closed_nodes = {} current = Node(start_position, None, 0) open_nodes[current.position] = current while open_nodes: current = open_nodes.popitem(False)[1] closed_nodes[current.position] = (current) if goal(current.position): return trace_path(current, open_nodes, closed_nodes) # Nodes bordering current for neighbor in self.environment.neighbors[current.position]: new_node = Node(neighbor, current, current.depth + 1) open_nodes[new_node.position] = new_node
同时使用双端队列和字典:
open_queue = deque() open_nodes = {} closed_nodes = {} current = Node(start_position, None, 0) open_queue.append(current) open_nodes[current.position] = current while open_queue: current = open_queue.popleft() del open_nodes[current.position] closed_nodes[current.position] = (current) if goal_function(current.position): return trace_path(current, open_nodes, closed_nodes) # Nodes bordering current for neighbor in self.environment.neighbors[current.position]: new_node = Node(neighbor, current, current.depth + 1) open_queue.append(new_node) open_nodes[new_node.position] = new_node
两个 双端队列 和 字典 是用C语言实现,并且将运行速度比 OrderedDict 其在纯Python实现。
OrderedDict 的优点是它具有O(1)getitem,setitem和delitem,就像常规字典一样。这意味着尽管纯python实现较慢,它的伸缩性也很好。
使用双端队列,列表或二叉树进行竞争的实现通常会在其中一个类别中放弃快速的big-Oh时间,以便在另一个类别中获得速度或空间上的好处。
更新: 从Python 3.5开始, OrderedDict() 现在具有C实现。尽管它还没有像其他一些容器那样经过高度优化。它应该运行 多 比纯Python实现更快。然后从Python 3.6开始,已对常规词典进行了排序(尽管尚不能保证排序行为)。那些应该跑得更快:-)