Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using std::deque::iterator (in C++ STL) for searching and deleting certain elements

I have encountered a problem invoking the following code:

#include<deque>
using namespace std;

deque<int> deq = {0,1,2,3,4,5,6,7,8};

for(auto it = deq.begin(); it != deq.end(); it++){
    if(*it%2 == 0)
        deq.erase(it);
}

which resulted in a segmentation fault. After looking into the problem I found that the problem resides in the way the STL manages iterators for deques: if the element being erased is closer to the end of the deque, the iterator used to point to the erased element will now point to the NEXT element, but not the previous element as vector::iterator does. I understand that modifying the loop condition from it != deq.end() to it < deq.end() could possibly solve the problem, but I just wonder if there is a way to traverse & erase certain element in a deque in the "standard form" so that the code can be compatible to other container types as well.

like image 994
William Huang Avatar asked Mar 19 '13 01:03

William Huang


People also ask

How do you delete an element in deque?

remove() method is used to remove the element present at the head of the Deque. Parameters: The method does not take any parameters. Return Value: This method returns the element present at the head of the Deque. Exceptions: The method throws NoSuchElementException is thrown if the deque is empty.

How do I use an iterator in deque?

Deque iterator() method in JavaThe elements will be returned in order from first (head) to last (tail). The returned iterator is a “weakly consistent” iterator. Parameters: This method does not accepts any parameter. Returns: This method returns an iterator over the elements in this deque in a proper sequence.

Can you iterate through a deque?

You can directly iterate over the deque.

Which function is used in STL to delete the element at the end of double ended queue?

Dequeue or Double Ended Queue is a generalized version of Queue data structure that allows insert and delete at both ends. insert_at_beg(): inserts an item at the front of Dequeue. insert_at_end(): inserts an item at the rear of Dequeue. delete_fr_beg(): Deletes an item from front of Dequeue.


2 Answers

http://en.cppreference.com/w/cpp/container/deque/erase

All iterators and references are invalidated [...]

Return value : iterator following the last removed element.

This is a common pattern when removing elements from an STL container inside a loop:

for (auto i = c.begin(); i != c.end() ; /*NOTE: no incrementation of the iterator here*/) {
  if (condition)
    i = c.erase(i); // erase returns the next iterator
  else
    ++i; // otherwise increment it by yourself
}

Or as chris mentioned you could just use std::remove_if.

like image 186
syam Avatar answered Oct 23 '22 23:10

syam


To use the erase-remove idiom, you'd do something like:

deq.erase(std::remove_if(deq.begin(),
                         deq.end(),
                         [](int i) { return i%2 == 0; }),
          deq.end());

Be sure to #include <algorithm> to make std::remove_if available.

like image 34
Fraser Avatar answered Oct 23 '22 23:10

Fraser