【问题标题】:Is there a way to loop over the elements in multiset or unordered_set while deleting and insert elements in c++有没有办法在 c++ 中删除和插入元素时遍历 multiset 或 unordered_set 中的元素
【发布时间】:2020-10-20 08:41:39
【问题描述】:

我想循环遍历 multiset 或 unordered_set 中的每个元素,并且在循环期间,我可以插入和删除元素。 例如:

unordere_set<int> myset = { 1, 2, 3, 4 };
for (auto it = myset.begin(); it != myset.end(); ++it) {
    myset.erase(*it);
    // do something that needs to use the set without *it like in a recursion function that takes the reference of the set
    myset.insert(*it);      
}

我不想创建该集合的副本,因为该集合可能非常大而且效率不高。

【问题讨论】:

  • 当你说 use the set without *it 你的意思是下面的代码不会使用 it 或者你希望在没有那个特定的情况下对 set 进行操作成员(例如在第一次迭代中对没有元素1 的集合做一些事情)?您可能只想让您的函数获取对集合的引用,以及对您希望对其进行操作的迭代器的引用
  • 我的意思是我希望在没有那个特定成员的情况下在片场上进行操作。
  • 也许使用filter iterator

标签: c++ unordered-set multiset


【解决方案1】:

我认为这段代码没有问题(虽然未经测试)

unordered_set<int> myset = { 1, 2, 3, 4 };
for (auto it = myset.begin(); it != myset.end(); ) {
    auto save = *it;
    it = myset.erase(it);
    // do something that needs to use the set without *it like in a recursion function that takes the reference of the set
    myset.insert(save);      
}

我的理由是 mysave.insert(save) 不应该使迭代器 it 无效,因为它不会导致 unordered_set 的重新散列,因为您所做的只是添加回以前删除的元素。但当然,这确实取决于您对 // do something ... 所做的工作

【讨论】:

    【解决方案2】:

    在遍历时尽量避免插入和删除。这是一个不好的建议。

    #include <vector>
    #include <unordered_set>
    using namespace std;
    
    int main() {
      unordered_set<int> s { 1, 2, 3, 4, 5, 6, 7 };
      vector<unordered_set<int>::const_iterator> s_add;
      vector<unordered_set<int>::const_iterator> s_del;
      for (auto itr = s.begin(); itr != s.end(); ++itr) {
        // Some conditions
        s_add.push_back(itr);
        // Some conditions
        s_del.push_back(itr);
      }
    
      for (auto itr : s_add) {
        s.insert(*itr);
      }
    
      for (auto itr : s_del) {
        s.erase(itr);
      }
    
      return 0;
    }
    

    【讨论】:

      【解决方案3】:

      根据cpprefrence,插入可能会影响unordered_set容器上的所有迭代器。

      如果由于插入而发生重新散列,则所有迭代器都是 无效。否则迭代器不受影响。参考文献不 无效。仅当新的元素数量为 大于max_load_factor()*bucket_count()

      如果插入是 成功时,获得的元素的指针和引用 被持有的节点句柄无效,并且指针和 在提取该元素之前获得的对该元素的引用变为 有效。

      我想知道您是否只想遍历容器并对其进行一些插入/删除操作,为什么不直接使用std::vector 容器和元素索引来插入/删除它们。

      如果您坚持使用unordered_set,您可以在while 循环中使用std::next 来迭代您的unordered_set 容器并对其进行一些插入/删除操作。

      请注意,由于您将在循环末尾插入相同的元素,因此不会触发重新散列算法。

      unordered_set<int> myset = { 1, 2, 3, 4 };
      unordered_set<int>::iterator it = myset.begin();
      int i = 0;
      
      while (it != myset.end()) {
      
          myset.erase(*it);
          // do something that needs to use the set without *it like in a recursion function that takes the reference of the set
          myset.insert(*it);
          it = next(myset.begin(), ++i);
      }
      

      【讨论】:

        【解决方案4】:

        你可以这样做 -

        multiset<int> myset = { 1, 2, 3, 4 };
        while(myset.begin()!=myset.end()) {
            myset.erase(myset.begin());
            //     or
            myset.erase(3);
        }
        

        【讨论】:

        • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-01
        • 2020-07-14
        • 2016-06-18
        • 2013-06-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多