我试图使用链接列表创建素数列表。
我的计划是使用两个迭代器来基本完成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;
}
答案 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
可能会使以下所有迭代器无效。
答案 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