C++ 迭代并删除std::set中的元素

C++ 迭代并删除std::set中的元素,c++,iterator,set,erase,C++,Iterator,Set,Erase,我有一个std::set,我需要删除类似的相邻元素: DnaSet::const_iterator next = dna_list.begin(); DnaSet::const_iterator actual = next; ++next; while(next != dna_list.end()) // cycle over pairs, dna_list is the set { if (similar(*actual, *next)) { Dna dna_

我有一个
std::set
,我需要删除类似的相邻元素:

DnaSet::const_iterator next = dna_list.begin();
DnaSet::const_iterator actual = next;
++next;

while(next != dna_list.end()) // cycle over pairs, dna_list is the set
{
    if (similar(*actual, *next))
    {
        Dna dna_temp(*actual);  // copy constructor
        dna_list.erase(actual); // erase the old one
        do
        {
           dna_temp.mutate(); // change dna_temp
        } while(!dna_list.insert(dna_temp).second);  // insert dna_temp
    }
    ++actual;
    ++next;
}

有时程序无法退出主循环。我想当我删除
dna\u列表中的最后一个元素时,问题就出现了。执行此任务的正确方法是什么?

使用
actual=next
而不是
++actual


一旦您删除
actual
,它将是一个无效的迭代器,因此
++actual
的行为将异常
next
应该保持不变,因此将
actual
赋值给
next
应该可以工作。

您最好的选择是创建一个使用
Simular()
谓词的比较函子。然后你需要做的就是用这个比较函子构造这个集,你就完成了。集合本身将看到两个相似的元素相同,并且只允许第一个元素进入

struct lt_different {
    bool operator()(int a, int b) {
        return a < b && !similar(a, b);
    }

private:
    bool similar(int a, int b)
    {
        // TODO:when are two elements similar?
        const int EPSILON = 2;
        return abs(a - b) < EPSILON;
    }
};

// ...
set<int> o;  // fill this set with your data

// copy your data to a new set that rejects similar elements
set<int,lt_different> s(o.begin(), o.end(), lt_different());
struct lt\u不同{
布尔运算符()(整数a,整数b){
返回a
您可以使用集合
s
:插入元素、删除元素、修改元素——集合本身将确保集合中不存在两个类似的元素

也就是说,你也可以自己写一个算法,如果只是为了另一个选择的话。查看
中的
std::nextant_find()
。它将发现两个连续相同元素的第一次出现;坚持那个立场。找到后,从该点找到与这些元素不同的第一个元素。最终会得到两个迭代器,它们表示一系列连续的相似元素。您可以使用集合的
erase()
方法删除它们,因为它有一个重载,需要两个迭代器


起泡、冲洗、重复整个过程。

我如何实现您的第一个想法?我需要为集合的元素实现
操作符==
?我不能这样做,因为相似的概念不同于平等的概念,我两者都需要。也许有什么方法可以告诉to
std::set
使用特定的函数(与
operator==
不同)来确定两个元素是否重复?我用示例代码更新了答案。是的,只需将自己的比较函数传递给集合的构造函数。