int main() {
    int t;
    cin >> t;
    while (t--) {
        ll n;
        cin >> n;
        set<int> list;
        vector<ll> vec;
        for (size_t i = 1; i <= n; i++) {
            list.insert(i);
        }
        bool more = true;
        while (more) {
            vec.clear();
            auto it = list.begin();
            if (list.size() == 1) {
                cout << "1 1" << endl;
                break;
            }
            vec.push_back(*it);
            ll num = *it;
            list.erase(it);
            int count = 1;
            auto itt = list.begin();
            bool y = false;
            for (itt; itt != list.end(); ) {   // ...(1)
                if (checkPrime(*itt)) {
                    vec.push_back(*itt);
                    num = *itt;
                    list.erase(itt);
                    count++;
                }
                else if (gcd(num, *itt) == 1) {
                    vec.push_back(*itt);
                    num = *itt;
                    list.erase(itt);
                    count++;
                }
                else itt++;
            }
            if (count == 1) {
                cout << "2 1" << num << endl;
            }
            else {
                cout << count << " ";
                for (size_t i = 0; i < vec.size(); i++) {
                    cout << vec[i] << " ";
                }
                cout << endl;
            }
            if (list.size() == 1) more = false;
        }
    }
    return 0;
}

该程序试图查找一个范围内的互质数。但是在(1)中的每个最后一次迭代之后,它会导致错误,表明Debug断言失败!表达式映射/集合迭代器不兼容。为什么会这样呢? checkPrime gcd 是用于检查数字是否为质数并分别查找两个数字的gcd的函数。

最佳答案

在迭代时修改容器并非易事。
当您删除当前的迭代器时,它不再是有效的迭代器。删除它后,将生成不兼容的操作:

list<int> l;
for (int i = 0; i < 10; i++) l.push_back(i);
for (auto it = l.begin(); it != l.end(); )
    l.erase(it);

删除当前的迭代器后:
  • 当前的迭代器无效
  • 当前的位置由列表(++)中的下一个元素占据。

  • 这不会导致错误:
    list<int> l;
    for (int i = 0; i < 10; i++) l.push_back(i);
    for (auto it = l.begin(); it != l.end(); )
        l.erase(it++)
    

    请注意,您不能使用 vector 。但是使用 vector ,您可以执行以下操作:

        vector<int> v = {1,2,3,4,5,6,7,8,9,0};
        int current_position = 0;
        for (auto it = v.begin(); it != v.end(); it = v.begin() + current_position)
        {
            //some logic there in current position which can change
            v.erase(it);
        }
    

    map 和树木会带来更复杂的事情。
    所以这就是您应该擦除的方式:list.erase(itt ++);

    同样,您的代码很少赌在工程上:
    int main()
    {
        int t;
        cin >> t;
        while (t--)
        {
            ll n;
            cin >> n;
            set<int> list;
            vector<ll> vec;
            for (size_t i = 1; i <= n; i++)  list.insert(i);
            bool more = true;
    
            if (list.size() == 1)
            {
                cout << "1 1" << endl;
                continue;
            }
    
            while (list.size() > 1)
            {
                vec.clear();
                auto it = list.begin();
                vec.push_back(*it);
                ll num = *it;
                list.erase(it);
                for (auto itt = list.begin(); itt != list.end(); )
                {
                    if (checkPrime(*itt) || gcd(num, *itt) == 1)
                    {
                        vec.push_back(*itt);
                        num = *itt;
                        list.erase(itt++);
                    }
                    else itt++;
                }
                if (vec.size() == 1)
                    cout << "2 1" << num << endl;
                else
                {
                    cout << vec.size() << " ";
                    for (auto n : vec) cout << n << " ";
                    cout << endl;
                }
            }
        }
        return 0;
    }
    

    关于c++ - C++设置迭代器导致错误。表达式:映射/设置迭代器不兼容,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/61039603/

    10-11 16:03
    查看更多