我有一个图表并多次遍历每个节点,直到我将其标记为最终完成并在将来的迭代中忽略它。重复此过程,直到标记所有节点
到目前为止,我有一个std::vector
存储所有节点的状态:节点完成时为finished[v] = 1
,否则为0。代码如下所示:
for every node v {
if finished[v] == 0 {
[...]
}
}
问题是,在计算结束时,只有少数节点没有被标记,但我仍然检查finshed[v] == 0
的每一个节点
将所有节点ID保存在向量中然后将其移除直到向量为空(我听说向量中移除元素并不是非常有效)会更好吗?
由于我已经将已完成节点的数量存储为一个宽整数,我可以移动向量末尾的所有标记节点并将其剪切(位于totalNumberOfNodes - numberOfFinishedNodes
),以防移动元素比删除更有效。或者这个场景中的向量是否仅低于其他数据结构?
答案 0 :(得分:0)
如果您需要它们保持特定的顺序:链接列表可能是唯一有效的解决方案(您可以考虑其他数据结构,如"绳索和#34;如果您愿意,但我怀疑您赢了&#39 ; t想要实现它们。)
如果您只需要它们保持排序顺序:std::multiset
也应该有效;只需删除您访问过的元素。
如果您根本不关心订单:只需保留要处理的所有节点的vector
个索引,而不是实际擦除中的元素中间,用最后一个元素交换它,然后弹出向量的背面。
答案 1 :(得分:0)
使用std::list<T>
:
#include <list>
std::list<int> unvisited_nodes;
// fill in unvisited_nodes with all nodes' ids
loop of you algorithm
{
// iterate only over unvisited nodes
for (auto it = unvisited_nodes.begin(); it != unvisited_nodes.end(); )
{
visit(*it);
if (shouldNotBeVisitedAgain(*it))
{
unvisited_nodes.erase(it++);
}
else
{
++it;
}
}
}
使用您的std::vector<T>
:
#include <vector>
std::vector<int> unvisited_nodes;
// fill in unvisited_nodes with all nodes' ids
loop of you algorithm
{
// iterate only over unvisited nodes
for (int i = 0; i < unvisited_nodes.size(); )
{
visit(unvisited_nodes[i]);
if (shouldNotBeVisitedAgain(unvisited_nodes[i]))
{
std::swap(unvisited_nodes[i], unvisited_nodes.back());
unvisited_nodes.pop_back();
}
else
{
++i;
}
}
}
关于从std::vector<T>
删除元素的方法:此操作只有O(N)
复杂度,以防您希望保留元素的原始顺序。如果删除后元素的顺序不需要相同,则可以优化此操作:
std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7 } ;
// now, let's remove element under index 3, v[3] == 4:
std::swap(v[3], v.back());
v.pop_back();
// now v == { 1, 2, 3, >7<, 5, 6 }