【问题标题】:Find if an item already exists in STL queue查找 STL 队列中是否已存在项目
【发布时间】:2012-05-11 12:02:45
【问题描述】:

我正在使用 STL 队列在图上实现 BFS(广度优先搜索)。如果队列中已经不存在该节点,我需要在队列中推送该节点。但是,STL 队列执行not allow iteration through its elements,因此我无法使用 STL 查找功能。

我可以在每个节点被访问时使用一个标志来标记它们,并仅在标志为假时推送它们,但是,我需要多次运行 BFS,并且每次之后我都必须重置所有标志,所以我最终使用了计数器而不是标志,但我仍然想知道是否有在队列中查找项目的标准方法。

【问题讨论】:

  • 您想要的是一个单独的数据存储来存储图表中节点的颜色。如果每个节点都有一个唯一的标识符可以用作键,那么您可以使用std::map 来存储节点的颜色(白色、灰色、黑色)。这将是O(log(n),因为std::map 在大多数实现中被实现为RB 树。
  • @Vikas:我相信这相当于为每个节点分配一个计数器。
  • BFS 中的每个节点都会经历三种状态,未访问、已访问但未完成、已完成。我真的不知道您为每个节点分配计数器是什么意思。但是如果你能做到保持一个节点的三态,你就可以使用它。

标签: c++ algorithm stl find queue


【解决方案1】:

我假设您正在 BFS 中实现“封闭集”的概念?这样做的标准方法是简单地维护一个单独的 std::setstd::unordered_set 已经遇到的元素。这样,您将获得 O(lg n) 或 O(1) 查找,而在遍历队列时,如果支持,将花费 O(n) 时间。

【讨论】:

  • 谢谢。我认为这可行,尽管我必须在每个 BFS 回合开始时清空集合。
  • @Ari:一轮是什么意思?
  • 我需要多次运行 BFS。我所说的回合是指我正在运行 BFS 算法的每次迭代 i。对于每个节点,我都有一个变量 c 在访问时递增。如果在迭代 i 中没有访问过该节点,我只访问每个节点,即 c
  • @Ari:好的。然后只需使 BFS 成为一个函数,并使您的封闭集成为函数内的局部变量。无需明确清除。
  • 我最终使计数器成为每个节点的成员变量。这使我不必在封闭/开放集中进行搜索。
【解决方案2】:

公认的答案很愚蠢。

BFS 搜索中的每个项目都将经历三种状态:未访问、已访问但未完成、已访问。出于搜索目的,您可以将其缩减为已访问或未访问...

你只需要使用一个标志...

旗帜只是交替出现。

嗯,第一次遍历树时,每个节点将从 false(未访问)开始,然后变为 true(已访问)。在第二次遍历时,它将切换到 true(未访问)并转到 false(已访问)。

所以你所要做的就是保留一个单独的标志,它只是在每次遍历时改变状态......

那么你的逻辑是

if ( visitedFlag ^ alternatingFlagStateOfTree )
{
    visitedFlag ^= 1;
}

基本上,alternatingFlagStateOfTree 仅用于指示是否访问了 true 或访问了 false 状态。每次运行都是交替的,所以我们只是交换它们。

这完全消除了 set()、所有内存开销等的需要,也消除了在运行之间重置标志值的任何需要。

此技术可用于更复杂的状态,只要遍历的所有项目的结束状态一致。您只需进行一些数学运算即可重置标志值以将状态返回到基本状态。

【讨论】:

  • 请善待提出或回答问题的人,即使您不喜欢他们。您可能想看看stackoverflow.com/conduct。我建议您删除答案中的第一句话,或者至少以更具建设性的方式对其进行措辞(您不同意哪一部分,...)。
猜你喜欢
  • 2012-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-05
相关资源
最近更新 更多