无需保留订单时删除 - 删除习语的改进

时间:2018-06-17 09:12:04

标签: c++ algorithm

流行的print("If You want to start the game, please enter 'start'." + "\n" + "Otherwise please enter 'quit' in order to quit the game.") startGame = True def StartGame_int(answer): if answer.lower() == "start": startGame = False return "Welcome to Vahlderia!" elif answer.lower() == "quit": startGame = False return "Thank You for playing Vahlderia!" + "\n" + "You can now close the window." else: return "Please enter either 'r' to start or 'q' to quit the game." def StartGame(): answ = input("- ") StartGame_int(answ) while startGame == True: StartGame() - remove_if成语保留了容器中保留的元素的顺序。我有一个案例,我想删除一些元素,但我不关心其余元素的顺序,因为它们将在以后被移动,无论如何。我想,那不是使用erase - remove_if,我可以扫描向量,并且 - 当找到要删除的元素时 - 我可以将它与向量的最后一个有效元素交换。我称之为成语erase - swap,可以轻松实现如下:

erase

由于不需要移动元素,我希望这个代码在大的向量或包含大对象的向量上始终比template<typename Object, typename Condition> void swap_erase(std::vector<Object>& v, const Condition& condition) { // Keeps track to one past the last element we want to keep. auto iter_to_last = v.end(); for(auto it = v.begin(); it < iter_to_last; ++it) { // If the erasure condition is fulfilled... if(condition(*it)) { // Increase by one to the left the "tail" of the // vector, made by elements we want to get rid of; // Swap the two elements. // Rewind the current iterator by 1, so at the // next iteration we test the element we just swapped. std::iter_swap(it--, --iter_to_last); } } // Erase the elements we pushed at the end of the queue. v.erase(iter_to_last, v.end()); } - remove_if更快。 但是,a quick benchmark显示两个are roughly equivalent由gcc 7.3.0和erase编译,在我的i7上为2.6GHz。

我的假设,实施或基准测试的方式错了吗?

编辑:事实证明我的假设是错误的。这是-Ofast的一种可能实现,它清楚地表明它不需要移动任何元素:

remove_if

1 个答案:

答案 0 :(得分:3)

您对remove_if如何运作的假设可能是错误的。也许你应该明确说明。

基本上remove_if最多移动一次未删除的元素,因此如果删除大多数元素,它会特别快。 (它可以通过首先扫描未被删除的数组的初始部分进行优化,在这种情况下,如果删除少量元素并且第一个删除的元素接近结尾,它也会很快。)

您的交换算法为每个要删除的元素执行一个swap,因此如果删除的元素很少,则最快。但是swap是不必要的,并且在某些情况下不必要地慢,因为它需要三个动作。你可以移动最后一个元素超过被删除元素的顶部,可能会保存两个数据副本。