遍历 STL 映射(集/多集)的最佳方法,同时元素可能会在循环期间被删除并重新插入?
Best way to traverse a STL map(set/multiset) while the element might be removed and inserted back during the loop?
我只是注意到这个函数对于实现DFS搜索算法似乎非常有用。
例如,我们知道遍历图形 {{A->B}、{B->C}、{A->C}、{C->A}} 的边,并且我们希望找到一条跨越所有边的路径:A->C->A->B
在我看到这种问题的时候,我将通过DSP来解决它,通过一个数据结构来表示已经看到/使用了哪个"节点/边缘"。
我通常只是使用一个向量来保存它并修改值(并修改回来(以模拟使用的节点
例如:
string now = "A";
vector<string> nexts = get_all_edges_starting_from(now);
for (int i=0; i<nexts.size(); i++) {
string next = nexts[i];
nexts[i] == "visited"; // assume no node named "visited"
if (go_recursive_and_find_path_cover_all_edges())
{
results.push_back(now); // some global or whatever variable to store the result
return true;
}
nexts[i] = next; // abandon the "visit" so the recursion can use node/edge next time
}
return false;
它可以找到,但与使用地图或集合/多集相比效率不高。但是,我真的不知道如何在循环期间听到元素并重新插入时遍历映射/集/多集。
例如,失败的示例可能是:
string now = "A";
multiset<string> nexts = get_all_edges_starting_from(now);
multiset<string>::iterator it = nexts.begin();
for (it != nexts.end()) {
string next = *(it);
nexts.erase(next); // visited
if (go_recursive_and_find_path_cover_all_edges())
{
results.push_back(now); // some global or whatever variable to store the result
return true;
}
nexts.insert(next); // abandon the "visit"
it++;
}
return false;
此示例将失败,因为我通过在循环内删除和添加元素来破坏元素的内存结构。
一般来说,我知道这是不可能的,因为当我们考虑在当前遍历 posisiton 之前添加"新"元素的情况时,可能没有定义行为。但是,在DFS的示例中,我们通常只是删除元素并添加元素"在返回之前被删除"。
有没有简单的方法可以做到这一点?
首先,目前尚不清楚多映射是否真的比向量好,因为它的内存局部性要差得多,因此请尝试两种实现策略并进行比较。
接下来,您的循环包含一些我们可以修复的基本效率低下:
for (auto it = nexts.begin(); it != nexts.end(); )
{
string next = *it;
auto it = nexts.erase(it);
if (...) { ... }
nexts.insert(it, std::move(next));
}
兴趣点:
- 不要按值删除,而是按迭代器删除。
- 插入带有提示,因为您已经知道元素的去向。
- 移动插入字符串,因为您不需要副本。
- 在 C++17 中,您甚至可以使用
extract
将字符串移出地图。
相关文章:
- 如何从使用 for 循环中的矢量大小的矢量中删除元素
- 从嵌套循环中的 std::list 中删除将返回访问冲突
- 删除功能不适用于串行通信后多个循环中的多个实例
- 我正在尝试使用 while 循环从字符串中删除字母,直到没有字母。我在这里做错了什么?
- c++ 循环访问对象列表并删除对象
- 循环以从字符数组中删除过多的空格 (C++)
- C++循环链表删除,计数从下一个节点开始
- c++ 在循环中删除迭代器(映射的映射)
- 遍历 STL 映射(集/多集)的最佳方法,同时元素可能会在循环期间被删除并重新插入?
- 循环依赖:无法删除不完整的类型
- 如何在每次循环迭代期间生成向量,存储数据,然后删除该向量?
- 在循环-C 中重新删除对象
- 在循环访问嵌套向量时删除元素
- 如何在不使用循环或迭代器的情况下检查所有列表元素并在满足条件时删除一个
- 射击时从列表中删除外星人 - 找出循环;"表达式:无法递增结束列表迭代器"
- C++循环链接列表 - 删除所有节点
- C++删除 for 循环中的列表成员
- 在开关盒循环中使用未删除的标识符来解析 CSV 文件
- 如何在C++的循环中从矢量中删除元素
- 循环删除所有给定值