从嵌套for循环中的列表中删除值

时间:2014-05-10 21:24:39

标签: c++ list

我试图使用链接列表创建素数列表。

我的计划是使用两个迭代器来基本完成Eratosthenes的Sieve。我启动一个迭代器并使其成为当前的素数,它将从2开始。它进入另一个迭代,删除该数字的每个倍数,不留下2的倍数和下一个增量的素数,在这种情况下将是3它退出第二个循环并以这个新列表重新开始。一旦完成,列表应该只填充素数。

这是我的代码:

#include <iostream>
#include <list>

using namespace std;

int main(){

    int maxnum = 1001;
    int prime;
    list<int> mylist;
    list<int>::iterator it1, it2;

    for(int i=2; i<maxnum; ++i)
        mylist.push_back(i);

    it2 = mylist.begin();

    for(it2; it2!=mylist.end(); ++it2){
        prime = *it2;
        it1 = it2;
        for(it1; it1!=mylist.end(); ++it1){
            if(*it1%prime == 0)
                mylist.erase(it1);
        }

    }

    for (it1 = mylist.begin(); it1!=mylist.end(); ++it1)
        cout << " " << *it1;
}

我找不到像这样使用嵌套列表的任何示例,因此我不知道使用列表执行此操作是否天生就是错误的。我一直坚持分段错误。

感谢您的帮助。

编辑:好的,我发现了我的问题。从现在开始,当使用列表时,我将总是迭代一段时间。这是工作代码。

#include <iostream>
#include <list>

using namespace std;

int main(){

    int maxnum = 1001;
    int prime;
    list<int> mylist;
    list<int>::iterator it1, it2;

    for(int i=2; i<maxnum; ++i)
        mylist.push_back(i);

    it2 = mylist.begin();

    while (it2!=mylist.end()){
        prime = *it2;
        it1 = it2;
        ++it1;
        while (it1!=mylist.end()){
            if(*it1%prime == 0)
                it1 = mylist.erase(it1);
            else
                ++it1;
        }
        ++it2;
    }
    it1 = mylist.begin();
    for (it1; it1!=mylist.end(); ++it1)
        cout << " " << *it1;
}

3 个答案:

答案 0 :(得分:0)

问题在于此代码:

for(it1; it1!=mylist.end(); ++it1){
  if(*it1%prime == 0)
    mylist.erase(it1);
}

当您致电mylist.erase(it1)时,它不再可用。它指向的元素已从列表中删除,因此您无法再对此it1进行迭代。

您可以使用提供下一个有效迭代器的erase的返回值,但在这种情况下,您不能再使用for循环,因为它甚至会在删除后迭代。

以下是正确使用erase的示例(应根据您的算法进行调整):

it1 = mylist.begin();
while (mylist.end() != it1)
{
   if(*it1%prime == 0) 
   {
     it1 = mylist.erase(it1);
   }
   else
   {
     ++it1;
   }
}

另一种选择是在擦除之前进行迭代。它适用于list,因为erase不会使其他列表迭代器无效。

it1 = mylist.begin();
while (mylist.end() != it1)
{
   iterator it3 = it1;
   ++it1;
   if(*it3%prime == 0) 
   {
     mylist.erase(it3);
   }
}

但这适用于vector,因为erase可能会使以下所有迭代器无效。

Source

答案 1 :(得分:0)

std::list<T>::erase()iterator返回到被删除项目后的下一个项目:

it1 = it2;
while (it1!=mylist.end()){
    if(*it1%prime == 0)
        it1 = mylist.erase(it1);
    else
        ++it1;
}

答案 2 :(得分:0)

for(it1; it1!=mylist.end(); ++it1){
        if(*it1%prime == 0)
            mylist.erase(it1);

替换为

++it1; //otherwise you actually delete the number you are checking!!!   
while (it1!=mylist.end())
   if((*it1%prime))             // imho the better way of checking ;)
      ++it1;
   else
      it1 = mylist.erase(it1);  //erase returns the next iterator