如何迭代列表并从中删除

How to iterate a list and erase from it?

本文关键字:删除 列表 何迭代 迭代      更新时间:2023-10-16

我在列表迭代器上遇到了很多麻烦,我之前询问了一个问题,但无法找到我正在寻找的解决方案。

我有一个圆形列表,我必须用节点n (步骤)替换节点n的值。然后,我必须删除节点n (步骤)。当我擦除时,它将迭代器放在删除元素之后的元素上。我需要在节点n处返回迭代器。我该怎么做,因为每次擦除N (步骤)时,我都会收到一个无效的迭代器。我的输入是5和2。

如果没有办法从列表中迭代和擦除,请告诉我是否有更好的数据架构可以这样做。我想到使用向量,但是我必须将元素转移下来,如果有很多元素,那将是昂贵的。

#include "roulette.h"
#include <iostream>
uint roulette(uint people, uint step)
{
    std::list<uint>::iterator iterator;
    for(uint i = people; i > 0; i--)
        gl_myList.push_front(i);
    iterator = gl_myList.begin();
    while(people > 1)
    {
        iterator = advanceList(iterator, step - 1);
        uint replaceValue = *iterator; // Node n's value
        auto tempIterator = advanceList(iterator, step);
        uint newValue = *tempIterator; //Node n + step value
        iterator = gl_myList.erase(tempIterator);
        //Makes it past the erase function ONCE.
        //Puts the iterator back to the correct spot, and sets it value
        while(*iterator != replaceValue)
        {
            advanceList(iterator, 1);
        }
        *iterator = newValue;
        people--;
    }
    return *iterator;
}

advancelist

#include "roulette.h"
std::list<uint>::iterator advanceList(std::list<uint>::iterator& start, uint step)
{
    for(uint i = 0; i < step; i++)
    {
        start++;
        if(start == gl_myList.end())
        {
            start = gl_myList.begin();
        }
    }
    return start;
}

您没有正确使用erase()呼叫的结果,也不使用下一次迭代之前检查.end()。我全都确定以下是您至少尝试做的事情。请注意,这仍然很脆

std::list<uint>::iterator advanceList(std::list<uint>::iterator& start, uint step)
{
    for(uint i = 0; i < step; i++)
    {
        if(++start == gl_myList.end())
            start = gl_myList.begin();
    }
    return start;
}
uint roulette(uint people, uint step)
{
    std::list<uint>::iterator it;
    for(uint i = people; i > 0; i--)
        gl_myList.push_front(i);
    it = gl_myList.begin();
    while (gl_myList.size() > 1)
    {
        it = gl_myList.erase(advanceList(it, step - 1));
        if (it == gl_myList.end())
            it = gl_myList.begin();
    }
    return *it;
}

让我们在代码中修复一个非常简单的错误。当您调用

时,Advancelist会修改其参数
auto tempIterator = advanceList(iterator, step);

iteratortempIterator均已更改。您想实现的目标吗?

在您的 advanceList中,如果启动在输入函数时末尾,则必须在输入循环之前将其替换为 begin

我相信,您不是以正确的方式解决此问题。

最好的方法是首先将必须删除的内容与必须保留的内容分开。您可以使用 std :: partition std :: Stable_partition 在header algorithm 中。然后,您可以轻松清洁地从容器中删除一系列元素。

示例:

#include <vector>
#include <algorithm>
using namespace std;
// ...
bool differentFrom3(int n) { return n != 3; }
vector<int> v = { 1, 3, 4, 2, 1, 3, 4, 3, 7, 3, 1 };
// move all the 3's to one end of the vector
vector<int>::iterator it = stable_partition(v.begin(), v.end(), differentFrom3);
// v is now arranged in the following order:
// { 1, 4, 2, 1, 4, 7, 1, 3, 3, 3, 3 }
//                        ^
//                        +--- it
//
// and it points to the first element whose value is 3 (in this case, v[7])
// Now you can delete everything from the it to the end of the vector.
v.erase(it, v.end());

我在这里使用 stable_partition ,因为它可以保持元素之间的相对位置。如果您不在乎,可以使用分区