快速存储桶实现

时间:2012-03-08 13:12:04

标签: c++ algorithm stl graph-theory

在图类中,我需要处理具有整数值的节点(主要是1-1000)。在每个步骤中,我想从图中删除节点及其所有邻居。另外,我想始终以最小值的节点开始。我很想过如何以最快的方式做到这一点,并决定做以下事情:

  • 使用附属列表存储图表
  • 有一个庞大的数组std::vector<Node*> bucket[1000]来存储节点的值
  • 始终存储最低非空桶的索引并保持跟踪
  • 我可以通过选择该索引的随机元素来快速找到最小值的节点,或者如果存储桶已经为空则增加索引
  • 从桶中删除所选节点可以在O(1)中清楚地完成,问题是为了删除邻居,我需要首先搜索所有邻居节点的桶桶[邻居值],这不是很快。

对此有更有效的方法吗?

我想过使用类似std::list<Node*> bucket[1000]的东西,并为每个节点分配一个指向其&#34; list元素&#34;的指针,这样我就可以从O(1)中的列表中删除该节点。使用stl列表是否可以实现这一点,显然可以使用普通的双链表来完成,我可以手工实现吗?

2 个答案:

答案 0 :(得分:1)

我最近为使用存储桶的优先级队列实现做了类似的事情。

我所做的是使用哈希表(unordered_map),这样,你不需要存储1000个空向量,你仍然可以获得O(1)随机访问(一般情况下,不保证)。现在,如果您只需要存储/创建此图表类一次,它可能无关紧要。在我的情况下,我需要创建每秒数十/数百个时间的优先级队列并使用哈希映射产生巨大的差异(由于我实际上有一个优先级元素时我只创建了无序的事实,所以不需要初始化1000个空哈希集)。散列集和映射是C ++ 11中的新增功能,但现在已经在std :: tr1中使用了一段时间,或者您可以使用Boost库。

我和你之间可以看到的唯一区别我的用例,就是你还需要能够删除相邻节点。我假设每个节点都包含一个指向它的邻居的指针列表。如果是这样,删除邻居应该k * O(1) k邻居的数量(一般来说,O(1),不保证,最坏的情况是unordered_map / set中的O(n)) 。您只需遍历每个相邻节点,获取其优先级,即可为哈希映射提供正确的索引。然后你找到优先级映射到的哈希集中的指针,这个搜索通常是O(1),一般来说,删除元素也是O(1)。

总而言之,我认为你很清楚要做什么,但我相信使用哈希映射/设置会使你的代码加速很多(取决于当然的确切用法)。对我而言,unordered_map<int, unordered_set>vector<set>的实施速度提升约为50倍。

答案 1 :(得分:1)

这是我要做的。节点结构:

struct Node {
    std::vector<Node*>::const_iterator first_neighbor;
    std::vector<Node*>::const_iterator last_neighbor;
    int value;
    bool deleted;
};

连接邻接列表并将它们放在一个std::vector<Node*>中以降低内存管理的开销。我使用软删除功能,因此更新速度并不重要。

按值将节点的指针排序到具有counting sort的另一个std::vector<Node*>。将所有节点标记为未删除。

按排序顺序迭代节点。如果已删除所考虑的节点,请转到下一个节点。否则,将其标记为已删除并迭代其邻居并将其标记为已删除。

如果您的节点连续存储在内存中,那么您可以在结构末尾以额外的Sentinel节点为代价省略last_neighbor,因为节点的last_neighborfirst_neighbor后续节点。