[英]What's wrong in this implementation of Bresenham’s circle drawing algorithm?
[英]What's wrong with this algorithm implementation [Sieve of Erathosthene]
我正在嘗試用C ++實現Eratosthene篩選 。 但是經過多次嘗試后,我總是遇到運行時錯誤。 我認為這與使用的迭代器狀態在某處被破壞有關。 我不能把手指放在它上面。 這是我的代碼:
//Sieves all multiples of the current sequence element
bool multiple_sieve(std::list<int>& num_list)
{
std::list<int>::iterator list_iter(num_list.begin());
std::list<int>::reverse_iterator last_element_iter(num_list.rbegin());
for(std::list<int>::iterator elements_iter(++list_iter);
elements_iter != num_list.end();)
{
if((*elements_iter % *list_iter == 0) &&
(*elements_iter <= *last_element_iter) && (*list_iter != 1))
num_list.erase(elements_iter);
else ++elements_iter;
}
return true;
}
std::list<int>& prime_sieve(std::list<int>& num_list)
{
for(std::list<int>::iterator list_iter(num_list.begin());
list_iter != num_list.end(); ++list_iter)
multiple_sieve(num_list);
return num_list;
}
我做錯了什么? 什么導致運行時錯誤?
更新:當我在我的測試中運行它時,我收到錯誤消息“列表迭代器不兼容”。
這一行:
num_list.erase(elements_iter);
因為您在迭代時修改列表會導致問題。 您可以這樣做以避免該問題:
elements_iter = num_list.erase(elements_iter);
ETA:刪除了擦除()使其他迭代器失效的東西(在這種情況下看起來很安全) - 只需將elements_iter設置為erase()的返回值,你就應該好了。
我不知道你為什么在這里使用列表。 在向量上運行篩子並在列表中保存質數更容易。
std::list<int> primes(int MAXN){
std::list<int> result;
std::vector<bool> sieve(MAXN+1,true);
for(int i=2;i<=MAXN;i++){
if(sieve[i]==true){
result.push_back(i);
if((long long)i*i<=MAXN) //prevent integer overflow
for(int j=i*i;j<=MAXN;j+=i)
sieve[j]=false;
}
}
return result;
}
我想我看到一個問題,它是std :: list.erase()。 erase() 僅使擦除的迭代器無效 - 所有到其他部分的迭代器都是有效的。 刪除后,繼續在for語句中使用它 - “elements_iter!= num_list.end()”。
要解決這個問題,你可以使用erase()在擦除之后返回迭代器的事實,如果擦除的oiterator是最后一個,則返回結束。 所以更換線:
num_list.erase(elements_iter);
通過
elements_iter = num_list.erase(elements_iter);
如果你還有問題,我建議你在Visual Studio下調試你的算法 - 它有debub版本的STL,所以如果出現錯誤,調試器會在線停止導致問題。
num_list.erase(elements_iter)
我不認為你應該這樣做,這會完全刪除列表中的數字,你寧願把它標記為非素數。
如果你真的想使用STL代替bool數組,那么最好在這個實現中使用std :: bitset(好吧,也可能有更好的)。
我已經發布了一個更高效的篩前 。
這適合我。 來自代碼的值得注意的修改:使用.erase(i++)
否則迭代器將失效,並從列表中的連續位置啟動multiple_sieve
,而不是始終從頭開始。
#include <iostream>
#include <list>
template<typename T, typename L>
void multiple_sieve(L &nums,
const typename L::iterator &begin, const typename L::iterator &end) {
T first = *begin;
typename L::iterator i(begin);
++i;
while (i != end)
if (*i % first == 0) nums.erase(i++);
else ++i;
}
template<typename T, typename L>
void prime_sieve(L &nums) {
typename L::iterator end = nums.end();
for (typename L::iterator i(nums.begin()); i != end; ++i)
multiple_sieve<T, L>(nums, i, end);
}
int main(int argc, char **argv) {
std::list<int> list;
for (int i = 2; i < 1000; i++)
list.push_back(i);
prime_sieve<int, std::list<int> >(list);
for (std::list<int>::iterator i(list.begin());
i != list.end(); i++)
std::cout << *i << std::endl;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.