正确迭代向量的建议

时间:2011-04-06 04:01:19

标签: c++ vector iterator

我写了一个程序来确定tic-tac-toe的游戏树。 我相信大部分代码都处于良好状态。 我编写了一个函数来比较向量的元素,以确定是否有任何元素是重复的。 重复的项目可以是真正相同的,也可以是对称的。 从矢量中删除重复的元素。 我的比较功能似乎存在错误消除元素的问题。 请看一下我如何迭代向量,看看语法/逻辑是否合理。

我的猜测是使用< >运营商可能是问题的一部分。 该函数的基本逻辑是比较第一个元素和最后一个元素,然后是倒数第二个元素,依此类推。在将第一个元素与所有元素进行比较之后,再次开始将第二个元素与其他元素进行比较,依此类推......

void compareAllGames(move& aMove) { /* aMove is a vector of games. games are a struct of data */
    vector<game>:: iterator frontIter = aMove.begin();
    vector<game>:: iterator rearIter = aMove.end() - 1;
    vector<game>:: iterator compIter;
    for (; frontIter < rearIter; frontIter++) { /* move along the games from first to last */
        for (compIter = aMove.end(); compIter > frontIter; ) { /* move along the games from last to first */
            /* checkForSymmetry compares *frontIter to all symmetries of *compIter */
            if (checkForSymmetry(*frontIter, *compIter)) {
                compIter--;
                aMove.erase(compIter + 1);
            }
            else {
                compIter--;
            }
        } /* reset iterators for next loop */
        compIter = aMove.end();
        rearIter = aMove.end();
    }
}

4 个答案:

答案 0 :(得分:2)

看起来您访问end的地方至少有一两个地方已超过容器的末尾。我没有尝试修复有些错综复杂的逻辑,而是建议:

如果您可以创建一个始终相邻排列对称解决方案的排序,则可以应用该顺序,然后将std::unique与谓词一起使用以删除重复项。

如果你不能这样做,那么使用remove_if而不是复杂的内循环:

void compareAllGames(move& aMove) { /* aMove is a vector of games. games are a struct of data */
    vector<game>:: iterator frontIter = aMove.begin();
    for (; frontIter < aMove.end() - 1; frontIter++) { /* move along the games from first to last */
        aMove.erase(std::remove_if(frontIter + 1, aMove.end(), std::bind1st(checkForSymmetry, *frontIter)), aMove.end());
    }
}

答案 1 :(得分:1)

for (; frontIter < rearIter; frontIter++) { /* move along the games from first to last */

你是对的:你应该使用!=代替<。它可能没有任何区别,但没有其他原因,你通常也想使用预增量而不是后增量,给出:

for (;frontIter != readiter; ++frontIter)
    for (compIter = aMove.end(); compIter > frontIter; ) { /* move along the games from last to first */

要反向遍历集合,通常想要使用reverse_iterator:

    vector<game>::reverse_iterator compIter;
    for (compIter=aMove.rbegin(); compIter != frontIter; ++compIter);

Offhand我不记得你是否可以直接将迭代器与reverse_iterator进行比较 - 你可能需要将fronIter转换为reverse_iterator来进行比较。

        /* checkForSymmetry compares *frontIter to all symmetries of *compIter */
        if (checkForSymmetry(*frontIter, *compIter)) {
            compIter--;
            aMove.erase(compIter + 1);
        }
        else {
            compIter--;
        }
    } /* reset iterators for next loop */

虽然转换不会完全简单,但看起来最终会变成std::remove_if的变体,因此您可以将其更改为使用标准算法。

答案 2 :(得分:1)

这不是一个真正的答案,只是为了向OP澄清我在评论中的含义。

/* aMove is a vector of games. games are a struct of data */
void compareAllGames( move &aMove ) 
{
    typedef vector<game>::iterator game_it;
    /* move along the games from first to last */
    for( game_it frontIter = aMove.begin(); frontIter != aMove.end(); ++frontIter ) 
    {
        /* move along the games from last to first */
        for( game_it compIter = aMove.end(); compIter != frontIter; --compIter )  
        {
            /* checkForSymmetry compares *frontIter to all symmetries of *compIter */
            if( checkForSymmetry( *frontIter, *compIter ) )
            {
                compIter = aMove.erase( compIter );
            }

        }
    }
}

答案 3 :(得分:0)

感谢所有评论。最后我简化了我的功能,它有两个令人困惑的循环,并确定不是将所有游戏添加到移动然后检查重复/对称,我可以添加一个游戏并将其与当前列表进行比较。这有两个优点:易于理解的简单编码和更低数量的比较。这段代码实际上也起作用并没有什么坏处。这些变化让我在对称函数中发现了一些错误。

这是我使用的最终功能:

bool compareAllGames(move& aMove) {
    vector<game>:: iterator frontIter = aMove.begin();
    vector<game>:: iterator rearIter = aMove.end() - 1;

    for (; frontIter != rearIter; ++frontIter) { // move along the games from first to last
        if (checkForSymmetry(*frontIter, aMove.back())) {
            aMove.pop_back();
            return true;
        }
    }
    return false;
}

现在我只需要将我的代码添加到该帐户中以获取获胜者,并且我将对tic tac toe游戏树进行适当的调整计数。移动的未调整计数(忽略获胜者)为:1,2,12,38,108,174,228,174,89和23.